summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cloos <cloos@freedesktop.org>2011-08-30 03:37:38 -0700
committerJames Cloos <cloos@freedesktop.org>2011-08-30 03:37:38 -0700
commit3ed3a482f75317f50821f6a43e4afc9997d0ae83 (patch)
tree058e7cfd31d145296f7a443f29da52ea5857efb8
parentf2a102d2e974ad0b6f7bd548b04c6fc39601d173 (diff)
xpdf-3.03xpdf-3.03
-rw-r--r--ANNOUNCE23
-rw-r--r--CHANGES387
-rw-r--r--COPYING3674
-rw-r--r--INSTALL40
-rw-r--r--Makefile.in8
-rw-r--r--README102
-rw-r--r--aconf-dj.h1
-rw-r--r--aconf-win32.h1
-rw-r--r--aconf.h.in1
-rwxr-xr-xconfigure12078
-rw-r--r--configure.in33
-rw-r--r--dj_make.bat6
-rw-r--r--doc/pdfdetach.1105
-rw-r--r--doc/pdfdetach.cat92
-rw-r--r--doc/pdfdetach.hlp101
-rw-r--r--doc/pdffonts.19
-rw-r--r--doc/pdffonts.cat64
-rw-r--r--doc/pdffonts.hlp72
-rw-r--r--doc/pdfimages.19
-rw-r--r--doc/pdfimages.cat71
-rw-r--r--doc/pdfimages.hlp75
-rw-r--r--doc/pdfinfo.121
-rw-r--r--doc/pdfinfo.cat82
-rw-r--r--doc/pdfinfo.hlp89
-rw-r--r--doc/pdftoppm.113
-rw-r--r--doc/pdftoppm.cat85
-rw-r--r--doc/pdftoppm.hlp92
-rw-r--r--doc/pdftops.125
-rw-r--r--doc/pdftops.cat243
-rw-r--r--doc/pdftops.hlp250
-rw-r--r--doc/pdftotext.113
-rw-r--r--doc/pdftotext.cat103
-rw-r--r--doc/pdftotext.hlp112
-rw-r--r--doc/sample-xpdfrc33
-rw-r--r--doc/xpdf.149
-rw-r--r--doc/xpdf.cat513
-rw-r--r--doc/xpdf.hlp529
-rw-r--r--doc/xpdfrc.5317
-rw-r--r--doc/xpdfrc.cat773
-rw-r--r--doc/xpdfrc.hlp769
-rw-r--r--fofi/FoFiBase.cc29
-rw-r--r--fofi/FoFiBase.h3
-rw-r--r--fofi/FoFiEncodings.cc6
-rw-r--r--fofi/FoFiEncodings.h6
-rw-r--r--fofi/FoFiIdentifier.cc632
-rw-r--r--fofi/FoFiIdentifier.h44
-rw-r--r--fofi/FoFiTrueType.cc373
-rw-r--r--fofi/FoFiTrueType.h34
-rw-r--r--fofi/FoFiType1.cc144
-rw-r--r--fofi/FoFiType1.h7
-rw-r--r--fofi/FoFiType1C.cc264
-rw-r--r--fofi/FoFiType1C.h35
-rw-r--r--fofi/Makefile.in2
-rw-r--r--goo/FixedPoint.cc51
-rw-r--r--goo/FixedPoint.h15
-rw-r--r--goo/GHash.cc24
-rw-r--r--goo/GHash.h12
-rw-r--r--goo/GList.cc27
-rw-r--r--goo/GList.h10
-rw-r--r--goo/GString.cc114
-rw-r--r--goo/GString.h23
-rw-r--r--goo/gfile.cc121
-rw-r--r--goo/gfile.h18
-rw-r--r--goo/gmem.cc44
-rw-r--r--goo/gmem.h2
-rw-r--r--goo/parseargs.c6
-rw-r--r--goo/parseargs.h7
-rw-r--r--ms_make.bat34
-rw-r--r--splash/Splash.cc4176
-rw-r--r--splash/Splash.h106
-rw-r--r--splash/SplashBitmap.cc95
-rw-r--r--splash/SplashBitmap.h8
-rw-r--r--splash/SplashClip.cc57
-rw-r--r--splash/SplashClip.h6
-rw-r--r--splash/SplashFTFont.cc142
-rw-r--r--splash/SplashFTFontEngine.cc45
-rw-r--r--splash/SplashFTFontEngine.h18
-rw-r--r--splash/SplashFTFontFile.cc30
-rw-r--r--splash/SplashFTFontFile.h14
-rw-r--r--splash/SplashFont.cc22
-rw-r--r--splash/SplashFontEngine.cc27
-rw-r--r--splash/SplashFontEngine.h19
-rw-r--r--splash/SplashMath.h143
-rw-r--r--splash/SplashPath.cc5
-rw-r--r--splash/SplashPath.h6
-rw-r--r--splash/SplashScreen.cc104
-rw-r--r--splash/SplashScreen.h11
-rw-r--r--splash/SplashState.cc58
-rw-r--r--splash/SplashState.h12
-rw-r--r--splash/SplashT1Font.cc41
-rw-r--r--splash/SplashT1FontEngine.cc6
-rw-r--r--splash/SplashT1FontEngine.h4
-rw-r--r--splash/SplashT1FontFile.cc11
-rw-r--r--splash/SplashT1FontFile.h6
-rw-r--r--splash/SplashTypes.h4
-rw-r--r--splash/SplashXPath.cc127
-rw-r--r--splash/SplashXPath.h14
-rw-r--r--splash/SplashXPathScanner.cc498
-rw-r--r--splash/SplashXPathScanner.h24
-rw-r--r--xpdf/Annot.cc307
-rw-r--r--xpdf/Annot.h23
-rw-r--r--xpdf/BuiltinFont.cc6
-rw-r--r--xpdf/BuiltinFont.h10
-rw-r--r--xpdf/CMap.cc222
-rw-r--r--xpdf/CMap.h22
-rw-r--r--xpdf/Catalog.cc630
-rw-r--r--xpdf/Catalog.h38
-rw-r--r--xpdf/CharCodeToUnicode.cc189
-rw-r--r--xpdf/CharCodeToUnicode.h4
-rw-r--r--xpdf/Decrypt.cc489
-rw-r--r--xpdf/Decrypt.h18
-rw-r--r--xpdf/Dict.cc11
-rw-r--r--xpdf/Dict.h8
-rw-r--r--xpdf/Error.cc50
-rw-r--r--xpdf/Error.h21
-rw-r--r--xpdf/FontEncodingTables.cc14
-rw-r--r--xpdf/FontEncodingTables.h14
-rw-r--r--xpdf/Function.cc281
-rw-r--r--xpdf/Function.h10
-rw-r--r--xpdf/Gfx.cc1401
-rw-r--r--xpdf/Gfx.h62
-rw-r--r--xpdf/GfxFont.cc1024
-rw-r--r--xpdf/GfxFont.h85
-rw-r--r--xpdf/GfxState.cc607
-rw-r--r--xpdf/GfxState.h58
-rw-r--r--xpdf/GlobalParams.cc1210
-rw-r--r--xpdf/GlobalParams.h158
-rw-r--r--xpdf/ImageOutputDev.cc41
-rw-r--r--xpdf/ImageOutputDev.h12
-rw-r--r--xpdf/JArithmeticDecoder.cc47
-rw-r--r--xpdf/JArithmeticDecoder.h4
-rw-r--r--xpdf/JBIG2Stream.cc1285
-rw-r--r--xpdf/JBIG2Stream.h8
-rw-r--r--xpdf/JPXStream.cc1126
-rw-r--r--xpdf/JPXStream.h45
-rw-r--r--xpdf/Lexer.cc56
-rw-r--r--xpdf/Link.cc145
-rw-r--r--xpdf/Link.h6
-rw-r--r--xpdf/Makefile.in91
-rw-r--r--xpdf/NameToCharCode.cc8
-rw-r--r--xpdf/NameToCharCode.h6
-rw-r--r--xpdf/NameToUnicodeTable.h3161
-rw-r--r--xpdf/Object.cc8
-rw-r--r--xpdf/Object.h28
-rw-r--r--xpdf/OptionalContent.cc500
-rw-r--r--xpdf/OptionalContent.h132
-rw-r--r--xpdf/Outline.cc36
-rw-r--r--xpdf/OutputDev.cc8
-rw-r--r--xpdf/OutputDev.h25
-rw-r--r--xpdf/PDFCore.cc213
-rw-r--r--xpdf/PDFCore.h17
-rw-r--r--xpdf/PDFDoc.cc234
-rw-r--r--xpdf/PDFDoc.h39
-rw-r--r--xpdf/PDFDocEncoding.cc6
-rw-r--r--xpdf/PSOutputDev.cc2342
-rw-r--r--xpdf/PSOutputDev.h79
-rw-r--r--xpdf/Page.cc119
-rw-r--r--xpdf/Page.h26
-rw-r--r--xpdf/Parser.cc44
-rw-r--r--xpdf/Parser.h11
-rw-r--r--xpdf/PreScanOutputDev.cc98
-rw-r--r--xpdf/PreScanOutputDev.h25
-rw-r--r--xpdf/SecurityHandler.cc236
-rw-r--r--xpdf/SecurityHandler.h7
-rw-r--r--xpdf/SplashOutputDev.cc1405
-rw-r--r--xpdf/SplashOutputDev.h54
-rw-r--r--xpdf/Stream-CCITT.h5
-rw-r--r--xpdf/Stream.cc934
-rw-r--r--xpdf/Stream.h87
-rw-r--r--xpdf/TextOutputDev.cc840
-rw-r--r--xpdf/TextOutputDev.h64
-rw-r--r--xpdf/UnicodeMap.cc21
-rw-r--r--xpdf/UnicodeMap.h4
-rw-r--r--xpdf/UnicodeMapTables.h10
-rw-r--r--xpdf/UnicodeTypeTable.cc41
-rw-r--r--xpdf/UnicodeTypeTable.h4
-rw-r--r--xpdf/XPDFApp.cc4
-rw-r--r--xpdf/XPDFCore.cc74
-rw-r--r--xpdf/XPDFCore.h28
-rw-r--r--xpdf/XPDFTree.cc40
-rw-r--r--xpdf/XPDFTree.h1
-rw-r--r--xpdf/XPDFTreeP.h1
-rw-r--r--xpdf/XPDFViewer.cc183
-rw-r--r--xpdf/XPDFViewer.h8
-rw-r--r--xpdf/XRef.cc158
-rw-r--r--xpdf/XRef.h10
-rw-r--r--xpdf/XpdfPluginAPI.cc4
-rw-r--r--xpdf/about-text.h34
-rw-r--r--xpdf/config.h24
-rw-r--r--xpdf/pdfdetach.cc223
-rw-r--r--xpdf/pdffonts.cc15
-rw-r--r--xpdf/pdfimages.cc3
-rw-r--r--xpdf/pdfinfo.cc47
-rw-r--r--xpdf/pdftoppm.cc16
-rw-r--r--xpdf/pdftops.cc8
-rw-r--r--xpdf/pdftotext.cc33
-rw-r--r--xpdf/xpdf.cc2
197 files changed, 29955 insertions, 17665 deletions
diff --git a/ANNOUNCE b/ANNOUNCE
index 1184040..b4dff6c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,4 +1,4 @@
-Subject: ANNOUNCE: Xpdf 3.02 - a PDF viewer for X
+Subject: ANNOUNCE: Xpdf 3.03 - a PDF viewer for X
Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the
@@ -11,11 +11,22 @@ components (pdftops, pdftotext, etc.) also run on Win32 systems and
should run on pretty much any system with a decent C++ compiler.
Major changes:
-* 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.
+* Added the "fixed pitch" text extraction mode.
+* Modified "pdftops -paper match" to handle PDF files with
+ different-sized pages, i.e., it will now select the matching paper
+ size on a page-by-page basis.
+* Add ability for pdftoppm to write to stdout.
+* Added the pdfdetach tool.
+* Implemented 256-bit AES decryption.
+* Commented out the t1lib section in the configure script -- t1lib has
+ some potential security holes, and hasn't been updated in years.
+* Redesigned the font configuration xpdfrc commands: removed the
+ displayFontT1, displayFontTT, displayNamedCIDFontT1,
+ displayCIDFontT1, displayNamedCIDFontTT, displayCIDFontTT, psFont,
+ psNamedFont16, and psFont16 commands; added the fontFile,
+ fontFileCC, psResidentFont, psResidentFont16, and psResidentFontCC
+ commands.
+* Switched from GPLv2 to dual v2/v3 licensing.
See the `CHANGES' file for a complete list of changes.
diff --git a/CHANGES b/CHANGES
index 0378f0d..cde9756 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1760,3 +1760,390 @@ Use a custom string formatter to avoid problems with locale-based decimal
Allow comments in PostScript-type functions.
Change the TrueType font parser (FoFiTrueType) to delete glyf table
entries that are too short.
+
+3.03 (2011-aug-15)
+------------------
+Added the "fixed pitch" text extraction mode.
+Modified "pdftops -paper match" to handle PDF files with
+ different-sized pages, i.e., it will now select the matching paper
+ size on a page-by-page basis.
+Add ability for pdftoppm to write to stdout.
+Added the pdfdetach tool.
+Implemented 256-bit AES decryption.
+Commented out the t1lib section in the configure script -- t1lib has
+ some potential security holes, and hasn't been updated in years.
+Redesigned the font configuration xpdfrc commands: removed the
+ displayFontT1, displayFontTT, displayNamedCIDFontT1,
+ displayCIDFontT1, displayNamedCIDFontTT, displayCIDFontTT, psFont,
+ psNamedFont16, and psFont16 commands; added the fontFile,
+ fontFileCC, psResidentFont, psResidentFont16, and psResidentFontCC
+ commands.
+Switched from GPLv2 to dual v2/v3 licensing.
+Performance: cache tiling patterns.
+Implemented text fills with pattern color spaces.
+Rewrote the image and image mask rendering code to be more accurate
+ and faster.
+Fixed a bug in PDFCore that could sometimes cause crashes at high zoom
+ levels.
+Implemented embedded CMap streams.
+Added the 'setSelection' command.
+Added the 'rotateCCW' and 'rotateCW' commands.
+Added the 'psFontPassthrough' xpdfrc command.
+Added the 'launchCommand' xpdfrc command.
+Implemented alpha-type soft masks.
+Added "Form: AcroForm|XFA|none" to pdfinfo output.
+Added support for image masks filled with pattern color spaces.
+Text search wasn't finding all occurrences of a string on rotated pages
+ (i.e., pages where the primary rotation, as displayed, was not
+ horizontal).
+The text extractor now uses "ActualText" spans if they are present.
+Modified PSOutputDev so it always check for transparency; if Splash is
+ not available, it now prints a warning.
+Handle the blending color space for soft masks.
+Added the disableFreeTypeHinting xpdfrc option.
+Added the psAlwaysRasterize xpdfrc option.
+Added support for transfer functions in the rasterizer.
+Optimized the JPEG 2000 decoder to use less memory.
+Do fill adjustment (similar to stroke adjustment) on simple
+ rectangular fills.
+Added the antialiasPrinting xpdfrc setting.
+Added '%i', '%j', and '%k' (mouse pointer page and position) to the
+ available options for the 'run' command.
+Links with the underlined border style were being drawn with the lines
+ over, instead of under, the text.
+Add #include <aconf.h> to XPDFTree.cc (to avoid problems with certain
+ compilers).
+Change XRef::fetch() to avoid infinite loops caused by odd damage to
+ the xref table (e.g., where a stream object's "Length" value is an
+ indirect reference that points to another stream object).
+Minor fix in GString.cc to deal with an error in newer C++ compilers
+ (pow() can take int or double args).
+Handle embedded fonts which are declared with the wrong font type,
+ including 8-bit fonts declared as CID fonts and vice versa; this
+ was causing various problems, including crashes and invalid
+ PostScript output.
+In text extractor, don't drop horizontally overlapping words onto a
+ separate line.
+The numbers in the operand to the TJ operator should be multiplied by
+ the current horizontal scaling parameter.
+Fixed a bug in the Type 1C-to-Type 1 font converter -- need to escape
+ strings in the font dictionary.
+The zero-font-size check in PSOutputDev.cc was broken.
+Fixes for the form field appearance regeneration code: handle Unicode
+ strings (by downconverting to Latin1); check for "True" in addition
+ to "Yes" as a button value.
+Modify XPDFTree to limit the widget height to 32767 pixels -- this
+ avoids crashes with very large outlines.
+Modify FoFiType1 to handle PFB headers in Type 1 font files.
+Allow image mask decode arrays to be [1.0 0.0] in addition to [1 0].
+Tweak the form field appearance regeneration code.
+PSOutputDev now sets up resources for DR dictionaries in forms (in
+ case the form field appearances are regenerated).
+For TrueType fonts which are marked symbolic, the cmaps should be
+ ignored.
+Change the handling of numeric characters in Unicode text output --
+ they are now treated as left-to-right, which isn't strictly correct,
+ but does result in correct visual formatting.
+Modify FoFiTrueType to handle bogus loca table entries where the
+ offset is past the end of the glyf table.
+Fixed shading pattern fills to do clipping and background fills
+ correctly.
+Change the code that reads the page tree to be more flexible with
+ regard to improperly constructed trees.
+Changed the PostScript header comment from "Produced by xpdf/pdftops
+ x.yy" to "XpdfVersion: x.yy" to make it (mostly) DSC-compliant.
+Fixed PSOutputDev to handle page rotation correctly where the PDF page
+ is rotated 90 or 270 degrees and the page width (before rotation) is
+ greater than its height (and vice versa for 0 or 180 degrees).
+Unbalanced save/restores inside form XObjects (which can be happen in
+ damaged or incorrectly constructed PDF files) could cause crashes.
+The CCITTFax decoder could go into an infinite loop on certain types
+ of corrupt input.
+Added the "drawAnnotations" xpdfrc command.
+Added the "psUncompressPreloadedImages" xpdfrc command.
+Escape newlines and other non-printable characters in the custom color
+ DSC comments in PostScript output.
+Added the tilingPatternFill and *ShadedFill functions to
+ PreScanOutputDev to speed it up.
+Too many elements in an image's Decode array should not be a fatal
+ error.
+Fixed a buffer overflow security hole in StreamPredictor.
+Empty pages (zero-length content streams and null contents) were
+ causing crashes in continuous view mode.
+Handle line dash arrays that start with a zero element correctly.
+PreScanOutputDev was not correctly detecting all transparency - in
+ some places, it was looking only at the blending mode, and not at
+ the opacity setting.
+Force halftone screen size to be a power of 2. This allows optimizing
+ the halftoning code.
+Fixed a bug in the JBIG2 MMR decoder (and also in the CCITTFax
+ decoder) that was causing array references with negative indexes.
+Fixed a bug in the transparency code that was causing memory overruns.
+Fixed a 64-bit bug in the ASCII85 encoder.
+The focusToPageNum was crashing in full-screen mode - it should simply
+ do nothing.
+Added '%p' (current page number) to the available options for the 'run'
+ command.
+Tweak the behavior with PDF files that have pages of different widths
+ in continuous mode: scroll horizontally to avoid blank space on the
+ left side (when changing pages via entering a page number or
+ clicking on a link).
+A closepath followed by a lineto should create a new subpath for the
+ lineto.
+Fixed a buffer overflow in the CCITTFax decoder.
+Adobe Acrobat appears to ignore the flatness setting when rasterizing
+ curves, so Xpdf now does the same. (Oddly, Acrobat passes the
+ flatness setting through to PostScript output, which ends up making
+ the PS file look different from the PDF file - so Xpdf continues to
+ pass flatness through to PS files, too.)
+Pdfimages now ignores tiling pattern fills (for performance reasons).
+Fixed a bug in PDFCore that could sometimes cause crashes at high zoom
+ levels.
+Use std::sort (with functors) in place of qsort (if available) - this
+ can be significantly faster.
+Hitting "close" while Xpdf is in full-screen mode (with only one file
+ open) was crashing.
+Tweak the TrueType font encoding deciphering algorithm.
+Rewrote the CCITTFax decoder inner loop - this fixes a security hole.
+Fixed two security holes (missing bounds checks) in the DCT decoder.
+Do the correct zooming for "Fit" and "FitR" destinations.
+Implement the rotation value in the form field appearance regeneration
+ code.
+When PSOutputDev rasterizes a page (because it contains transparency),
+ the image is broken into stripes if it is above a size threshold.
+Don't clip the other page boxes to the MediaBox at the intermediate
+ (Pages) nodes; only do it at the leaf (Page) nodes - the other boxes
+ can be specified before the MediaBox is specified.
+Split several special cases off from Splash::pipeRun, for performance.
+Add a sanity check for excessively large font sizes (which caused
+ problems because Xpdf tried to allocate memory for a font cache).
+Fixed a bug in the GfxCIDFont constructor involving reading the
+ vertical metrics.
+Rewrote the code that handles annotation transforms - it was not
+ handling non-rectangular transforms correctly.
+Tweak the Type 3 bbox code to allow some slack on the left/bottom
+ edges, as well as the top/right edges.
+Fixed a bug that was causing problems rendering Type 3 fonts to 1-bit
+ monochrome output.
+Handle the case where AES padding is invalid.
+Changed XRef::getNumObjects to return the number of used entries,
+ instead of the same value as returned by XRef::getSize().
+Ignore bogus entries in the TrueType table directory instead of
+ immediately giving up on the font.
+Fixed a bug in the radial shading code that could cause divide-by-zero
+ errors.
+Tweaked the TrueType font fixup code to deal with an extra zero entry
+ at the end of the loca table.
+Increased font cache sizes to improve performance.
+Tweaked the TrueType notdef kludge to skip the notdef glyph only if it
+ was caused by a character for which a Unicode/MacRoman mapping could
+ not be found.
+Added another font size sanity check, this time for Type 3 glyphs.
+Added initial support for optional content (layers) - no GUI yet.
+For CID fonts that specify the 'Adobe-Identity' or 'Adobe-UCS'
+ collection, use an identity mapping for char code-to-Unicode
+ conversion.
+Updated the error function to take a category argument, and to use
+ GString::format instead of printf; added an error callback.
+The PDF spec claims that names are limited to 127 chars, but Distiller
+ 8 will produce longer names, and Acrobat 8 will accept longer names
+ -- Xpdf will now handle them, too.
+Change the Catalog code so it doesn't load the entire page tree at
+ startup (this only helps the command line tools - the viewer scans
+ all of the pages at startup).
+Clip opacity values to the range [0,1].
+Handle glyph names of the form 'unixxxx' (similar to Ann, Axx, etc.).
+Resolution of rasterized pages in PostScript output was not being
+ computed correctly (resulting in overly large images).
+Extend the mapUnknownCharNames config command to cover CID fonts.
+Zero-length segments in the middle of stroked paths were not being
+ handled correctly -- they should be completely ignored, except for
+ the special case of a zero-length path with round line caps.
+Various optimizations to the Splash rasterizer.
+Allow "Identity" and "Default" as the transfer function in soft masks.
+Tweaked the ToUnicode CMap parser to allow <00xx> char codes for 8-bit
+ fonts.
+TextPage::clear() was not clearing the lists of underlines and links.
+Changed the CCITTFax decoder to correctly handle the interaction
+ between the EndOfLine and EncodedByteAlign parameters.
+Fixed a bug where xpdf wouldn't go to a destination specified on the
+ command line, if continuous mode was enabled
+ (xpdf -cont file.pdf +foo).
+Fixed a bug in the FreeType interface code which was causing incorrect
+ positioning/sizing of characters.
+Tweaked the FreeType interface code - use 'light' hinting with Type 1
+ fonts (because it generally looks better).
+Tweak the Windows font searching code to handle "Black" fonts.
+Fixed a bug in the PostScript-type function parser -- real numbers
+ that start with a decimal point weren't being handled correctly.
+Changed the way filled-and-stroked text is handled -- use Splash to do
+ both the fill and the stroke (rather than using the font ending to
+ do the fill and Splash to do the stroke); also turn off stroke
+ adjustment when drawing stroked text.
+Ignore generation numbers on compressed objects (to match Adobe's
+ behavior).
+Changed the PostScript PageSize policy from 3 to 6 (choose next
+ largest paper size, don't rescale).
+Check that the mask values for color key masked images are in range --
+ both Ghostscript and Distiller choke on the PostScript if invalid
+ mask colors are specified.
+Fixed a bug in generic region decoding in the JBIG2 decoder.
+Fixed the lexer to handle large real numbers correctly.
+Pdftops wasn't correctly handling tiling patterns that use both fill
+ and stroke operators.
+Report an error if the Size array in a sampled function includes any
+ zeros.
+The PostScriptFunction.codeString field wasn't being initialized
+ correctly.
+Invalid object streams were not being handled correctly.
+Check for loops in xref tables.
+Handle the case where a content stream ends after the 'ID' operator
+ which starts inline image data.
+Check for invalid object streams (i.e., an object stream can't be
+ inside another object stream.
+Add a recursion limit to the object parser - this avoids stack
+ overflows with various sorts of damaged PDF files.
+Handle various parameter settings in the extended graphics state
+ dictionary.
+An invalid document outline (missing fields) could cause a crash.
+Added an overprint preview mode (for CMYK output only).
+Correctly handle FitH/BH/V/BV link destinations that contain null
+ values for positioning parameters.
+If the PDF file doesn't define a BaseURI, set one based on the
+ location of the PDF file -- this allows relative links to be handled
+ correctly.
+Use ResusableStreamDecode when generating Level 3 PostScript for an
+ explicitly masked image.
+Tweak the Type 1 font parser to handle encodings with multiple
+ characters on one line.
+Invert subtractive color components before passing them to the
+ blending function.
+Fix an invalid array access in SplashOutputDev::setSoftMask() in CMYK
+ mode.
+A PS interpreter may attempt to read past the end of a preloaded
+ image, so we need to check for that.
+Fixed several overflow/uninit bugs in JBIG2Stream.
+Fix the CCITTFax decoder to correctly find end-of-file (RTC/EOFB)
+ markers when the EndOfLine parameter is false.
+Don't limit the startxref offset to 10 digits - some PDF generators
+ use extra leading zeros.
+Use the "DV" (default value) field in text annotations if the "V"
+ (value) field is missing.
+Increase the number of digits printed for floating point numbers in
+ PostScript output -- it was running into numerical accuracy problems
+ on large pages.
+Fixed integer overflow bugs in Catalog.cc and GfxFont.cc.
+Zero-length tables in TrueType fonts should be treated as missing.
+ToUnicode CMaps map char codes to Unicode; .cidToUnicode files map
+ CIDs to Unicode -- ToUnicodeCMaps were being handled incorrectly.
+Added the "psRasterResolution" and "psRasterMono" xpdfrc commands.
+Added code to FoFiTrueType to check for entries in the table directory
+ with bogus tags -- this handles the case where the number of tables
+ given in the header is too high.
+Negative shift values in the PostScript bitshift operator were being
+ handled incorrectly.
+GfxICCBasedColorSpace was not correctly bounds-checking the number of
+ components.
+Check SampledFunction input values for NaNs.
+Fix a divide-by-zero when the page width or height is zero.
+Fix a bug positioning text in PostScript output - if the last char in
+ a string has an incorrect width in the PDF font object, that messes
+ up the total string width, so we have to position individual chars.
+In PostScript output, if CID font substitution fails, drop all text in
+ that font.
+Handle PDF files that set the stream/string decryption filters to
+ Identity (i.e., no encryption).
+Avoid passing a zero font size to FreeType.
+Tweak raw mode in the text extractor to handle words on the same line
+ drawn in the wrong order.
+Pdftops was generating a singular transform matrix for annotations
+ whose bounding boxes had zero width or height.
+Handle embedded OpenType CFF fonts with CIDToGIDMaps.
+Remove the old kludge from PSOutputDev that was converting char 32
+ from ".notdef" to "space".
+Allow CCITTFax images to be more than 32k pixels wide.
+Modified the CMap parser to handle usecmap with Identity-H/V.
+Added some parameter checking in the JPX decoder.
+Added checks for infinite loops in PDF objects - for color spaces,
+ functions, optional content, and outline items.
+Add support for mouse button bindings up to button 32 (old limit was
+ 7).
+Fixed a bug in the decryption code for revision 3 with keyLength < 16
+ -- the owner password was not being handled correctly. [Thanks to
+ Matthias Franz.]
+Optimize SampledFunction: pull index computation code out of the
+ transform function; cache the last transform.
+Tweaked the font naming algorithm in PSOutputDev.
+Treat mirrored (as opposed to rotated) text the same as upright text
+ in pdftotext.
+Fixed buffer overflows in Splash and SplashBitmap.
+Check for bogus character codes (e.g., <ffffffff>) in ToUnicode CMaps.
+The radial shading code (in both Gfx.cc and PSOutputDev.cc) was not
+ computing the s bounds properly.
+Drop empty subpaths in clip and fill (but not stroke) operations -
+ this can significantly speed up clip performance in the weird case
+ where a PDF file does "<x> <y> <w> <h> re <x> <y> m h W n".
+Added code to FoFiTrueType to check for an invalid loca format field
+ in the head table.
+The axial shading code (in Gfx.cc, but not PSOutputDev.cc) was not
+ computing the incremental polygon vertices correctly.
+Set the character width in TextOutputDev to something sensible for
+ vertical fonts.
+Added basic support to the text extractor for vertical writing mode.
+The non-interactive tools (pdftotext, pdftops) now free Page objects
+ after using them, avoiding performance problems with pages that have
+ huge resource dictionaries.
+Check for line dash arrays like [0], and draw nothing at all (to match
+ Acrobat's behavior).
+Add a sanity check for the ascent/descent values in FontDescriptors.
+Single-point paths with a line dash were causing a crash.
+Correctly handle Level 3 PostScript output with masked images inside
+ patterns.
+Tweaked the xref repair code so that it runs if the catalog is messed
+ up (in addition to running if the xref table is damaged).
+If Indexed color space tables (streams or strings) are too small,
+ reduce the max index instead of throwing away the color space.
+Change the CMap parser to allocate memory only when it sees a mapping,
+ not when it sees a 'codespacerange' declaration -- this avoids
+ allocating huge amounts of memory for CMaps with large, unused
+ codespaceranges.
+In monochrome mode, treat lines with width <= 1 as hairlines (to match
+ Acrobat's behavior).
+Cache the last transform for PostScript-type functions.
+Added the "-rawdates" option to pdfinfo.
+Optimized ImageStream::getLine().
+Fixed the Hue, Saturation, Color, and Luminosity blend functions to
+ match Adobe's spec.
+Fixed the non-isolated group compositing computation.
+Skip extraneous unused data at the end of JBIG2 segments.
+Change the algorithm that stroke/fill adjustment uses so that the
+ edges of adjacent strokes/fills line up.
+Do stroke adjustment on end caps when cap style is butt or projecting.
+Fixed a security hole: Gfx.parser was not being initialized to NULL.
+Fixed a security hole: integer bounds check in the Type 1 encoding
+ parser in FoFiType1.cc.
+If an embedded font object is invalid or non-existent, do font
+ substitution (same as if there were no embedded font).
+TextOutputDev was reusing an old font in the case where the font
+ changed but the font size and character positioning stayed the same.
+When starting a transparency group, copy the fill/stroke colors from
+ the graphics state.
+Tweaked the fixed-point code.
+When a TrueType font is declared resident (with a psFont command),
+ don't munge the encoding.
+Look for URIs starting with "www." and treat them as absolute "http:"
+ URIs, not as relative URIs (to match Adobe's behavior).
+Added code to FoFiTrueType to check for a zero-entry cmap table.
+Tweaked the font substitution code to do a better job of scaling the
+ substituted font.
+Require at least two splits in the axial shading color bisection.
+Optimized JBIG2Stream::readGenericBitmap().
+JPXStream wasn't correctly handling row padding for images with fewer
+ than 8 bits per component.
+Optimized the ToUnicode CMap parser.
+Added a "whole words only" option to text searches.
+Check for valid component parameters in the DCT decoder.
+Implement embedding of external 16-bit fonts (without subsetting) in
+ PostScript output.
+Added the minLineWidth xpdfrc command.
+Added warning messages for font substitutions.
diff --git a/COPYING3 b/COPYING3
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING3
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/INSTALL b/INSTALL
index 6c6db87..366a46d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,11 +1,11 @@
Xpdf
====
-version 3.02
-2007-feb-27
+version 3.03
+2011-aug-15
The Xpdf software and documentation are
-copyright 1996-2007 Glyph & Cog, LLC.
+copyright 1996-2011 Glyph & Cog, LLC.
Email: derekn@foolabs.com
WWW: http://www.foolabs.com/xpdf/
@@ -28,15 +28,6 @@ different systems.
*** UNIX ***
**************
-* Install t1lib (if desired). The resulting library (libt1) and
- include files (t1lib.h and t1libx.h) should be placed somewhere on
- the standard search paths. Alternatively, when you configure xpdf,
- you can use the following options to tell configure where to find
- the t1lib files:
-
- --with-t1-library=PATH
- --with-t1-includes=PATH
-
* Install FreeType 2 (this is required). WARNING: You must have
version 2.0.5 or newer. Some older versions of XFree86 ship with an
older version of FreeType, which means you'll need to explicitly set
@@ -103,6 +94,7 @@ different systems.
xpdf/pdftotext
xpdf/pdfinfo
xpdf/pdffonts
+ xpdf/pdfdetach
xpdf/pdftoppm
xpdf/pdfimages
@@ -162,9 +154,9 @@ configure script version.
*** Win32 ***
***************
-The non-X programs (pdftops, pdftotext, pdfinfo, pdffonts, pdfimages,
-and pdftoppm) will compile with both gcc (from cygwin), djgpp (the
-Delorie port of gcc) and Microsoft Visual C++.
+The non-X programs (pdftops, pdftotext, pdfinfo, pdffonts, pdfdetach,
+pdfimages, and pdftoppm) will compile with both gcc (from cygwin),
+djgpp (the Delorie port of gcc) and Microsoft Visual C++.
With cygwin, the build procedure is the same as for Unix:
@@ -182,22 +174,14 @@ port (thanks to Michael A. Richmond for these instructions):
* make sure you have the lesstif, XFree86-base, and XFree86-prog
cygwin packages installed (all from the "XFree86" category)
- * to build t1lib:
- - cd T1Lib-x.y
- - ./configure --without-x
- - make without_doc
- - make install
- (this should install /usr/local/include/t1lib.h and
- /usr/local/lib/libt1.a)
-
* to build xpdf:
- cd xpdf-x.yy
- ./configure --with-t1-library=/usr/local/lib
--with-t1-includes=/usr/local/include
- --with-freetype2-library=/usr/X11R6/lib
- --with-freetype2-includes=/usr/X11R6/include/freetype2
- --with-Xm-library=/usr/X11R6/lib
- --with-Xm-includes=/usr/X11R6/include
+ --with-freetype2-library=/usr/lib
+ --with-freetype2-includes=/usr/include/freetype2
+ --with-Xm-library=/usr/lib
+ --with-Xm-includes=/usr/include
(all on one line)
- make
(this should build xpdf.exe, in addition to the command line
@@ -245,4 +229,4 @@ With the Microsoft tools:
* Type "ms_make"
The dj_make and ms_make scripts don't build pdftoppm -- you'll need to
-install t1lib and FreeType 2 before you can compile pdftoppm.
+install FreeType 2 before you can compile pdftoppm.
diff --git a/Makefile.in b/Makefile.in
index c08e721..e4391e6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -61,6 +61,12 @@ pdffonts:
cd @UP_DIR@splash; $(MAKE)
cd @UP_DIR@xpdf; $(MAKE) pdffonts$(EXE)
+pdfdetach:
+ cd goo; $(MAKE)
+ cd @UP_DIR@fofi; $(MAKE)
+ cd @UP_DIR@splash; $(MAKE)
+ cd @UP_DIR@xpdf; $(MAKE) pdfdetach$(EXE)
+
pdftoppm:
cd goo; $(MAKE)
cd @UP_DIR@fofi; $(MAKE)
@@ -82,6 +88,7 @@ install: dummy
$(INSTALL_PROGRAM) xpdf/pdftotext$(EXE) $(DESTDIR)@bindir@/pdftotext$(EXE)
$(INSTALL_PROGRAM) xpdf/pdfinfo$(EXE) $(DESTDIR)@bindir@/pdfinfo$(EXE)
$(INSTALL_PROGRAM) xpdf/pdffonts$(EXE) $(DESTDIR)@bindir@/pdffonts$(EXE)
+ $(INSTALL_PROGRAM) xpdf/pdfdetach$(EXE) $(DESTDIR)@bindir@/pdfdetach$(EXE)
@X@ $(INSTALL_PROGRAM) xpdf/pdftoppm$(EXE) $(DESTDIR)@bindir@/pdftoppm$(EXE)
$(INSTALL_PROGRAM) xpdf/pdfimages$(EXE) $(DESTDIR)@bindir@/pdfimages$(EXE)
-mkdir -p $(DESTDIR)@mandir@/man1
@@ -90,6 +97,7 @@ install: dummy
$(INSTALL_DATA) $(srcdir)/doc/pdftotext.1 $(DESTDIR)@mandir@/man1/pdftotext.1
$(INSTALL_DATA) $(srcdir)/doc/pdfinfo.1 $(DESTDIR)@mandir@/man1/pdfinfo.1
$(INSTALL_DATA) $(srcdir)/doc/pdffonts.1 $(DESTDIR)@mandir@/man1/pdffonts.1
+ $(INSTALL_DATA) $(srcdir)/doc/pdfdetach.1 $(DESTDIR)@mandir@/man1/pdfdetach.1
@X@ $(INSTALL_DATA) $(srcdir)/doc/pdftoppm.1 $(DESTDIR)@mandir@/man1/pdftoppm.1
$(INSTALL_DATA) $(srcdir)/doc/pdfimages.1 $(DESTDIR)@mandir@/man1/pdfimages.1
-mkdir -p $(DESTDIR)@mandir@/man5
diff --git a/README b/README
index 71fd62e..e97791c 100644
--- a/README
+++ b/README
@@ -1,11 +1,11 @@
Xpdf
====
-version 3.02
-2007-feb-27
+version 3.03
+2011-aug-15
The Xpdf software and documentation are
-copyright 1996-2007 Glyph & Cog, LLC.
+copyright 1996-2011 Glyph & Cog, LLC.
Email: derekn@foolabs.com
WWW: http://www.foolabs.com/xpdf/
@@ -24,35 +24,36 @@ PDF text extractor, PDF-to-PostScript converter, and various other
utilities.
Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X
-components (pdftops, pdftotext, etc.) also run on Win32 systems and
-should run on pretty much any system with a decent C++ compiler.
+components (pdftops, pdftotext, etc.) also run on Windows and Mac OSX
+systems and should run on pretty much any system with a decent C++
+compiler. Xpdf will run on 32-bit and 64-bit machines.
-Xpdf is designed to be small and efficient. It can use Type 1 or
-TrueType fonts.
+License & Distribution
+----------------------
-Distribution
-------------
-
-Xpdf is licensed under the GNU General Public License (GPL), version
-2. In my opinion, the GPL is a convoluted, confusing, ambiguous mess.
-But it's also pervasive, and I'm sick of arguing. And even if it is
-confusing, the basic idea is good.
+Xpdf is licensed under the GNU General Pulbic License (GPL), version 2
+or 3. This means that you can distribute derivatives of Xpdf under
+any of the following:
+ - GPL v2 only
+ - GPL v3 only
+ - GPL v2 or v3
-In order to cut down on the confusion a little bit, here are some
-informal clarifications:
+The Xpdf source package includes the text of both GPL versions:
+COPYING for GPL v2, COPYING3 for GPL v3.
-- I don't mind if you redistribute Xpdf in source and/or binary form,
- as long as you include all of the documentation: README, man pages
- (or help files), and COPYING. (Note that the README file contains a
- pointer to a web page with the source code.)
+Please note that Xpdf is NOT licensed under "any later version" of the
+GPL, as I have no idea what those versions will look like.
-- Selling a CD-ROM that contains Xpdf is fine with me, as long as it
- includes the documentation. I wouldn't mind receiving a sample
- copy, but it's not necessary.
+If you are redistributing unmodified copies of Xpdf (or any of the
+Xpdf tools) in binary form, you need to include all of the
+documentation: README, man pages (or help files), COPYING, and
+COPYING3.
-- If you make useful changes to Xpdf, please make the source code
- available -- post it on a web site, email it to me, whatever.
+If you want to incorporate the Xpdf source code into another program
+(or create a modified version of Xpdf), and you are distributing that
+program, you have two options: release your program under the GPL (v2
+and/or v3), or purchase a commercial Xpdf source license.
If you're interested in commercial licensing, please see the Glyph &
Cog web site:
@@ -63,7 +64,7 @@ Cog web site:
Compatibility
-------------
-Xpdf is developed and tested on a Linux 2.4 x86 system.
+Xpdf is developed and tested on Linux.
In addition, it has been compiled by others on Solaris, AIX, HP-UX,
Digital Unix, Irix, and numerous other Unix implementations, as well
@@ -72,8 +73,8 @@ X11 and has Unix-like libraries. You'll need ANSI C++ and C compilers
to compile it.
The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdffonts,
-pdftoppm, and pdfimages) can also be compiled on Win32 systems. See
-the Xpdf web page for details.
+pdfdetach, pdftoppm, and pdfimages) can also be compiled on Windows
+and Mac OSX systems. See the Xpdf web page for details.
If you compile Xpdf for a system not listed on the web page, please
let me know. If you're willing to make your binary available by ftp
@@ -101,10 +102,9 @@ or:
Source code and several precompiled executables are available.
-Announcements of new versions are posted to several newsgroups
-(comp.text.pdf, comp.os.linux.announce, and others) and emailed to a
-list of people. If you'd like to receive email notification of new
-versions, just let me know.
+Announcements of new versions are posted to comp.text.pdf and emailed
+to a list of people. If you'd like to receive email notification of
+new versions, just let me know.
Running Xpdf
@@ -123,30 +123,48 @@ To generate a plain text file, run pdftotext:
pdftotext file.pdf
-There are four additional utilities (which are fully described in
+There are five additional utilities (which are fully described in
their man pages):
pdfinfo -- dumps a PDF file's Info dictionary (plus some other
useful information)
pdffonts -- lists the fonts used in a PDF file along with various
information for each font
+ pdfdetach -- lists or extracts embedded files (attachments) from a
+ PDF file
pdftoppm -- converts a PDF file to a series of PPM/PGM/PBM-format
bitmaps
pdfimages -- extracts the images from a PDF file
Command line options and many other details are described in the man
-pages (xpdf.1, etc.) and the VMS help files (xpdf.hlp, etc.).
+pages (xpdf(1), etc.) and the VMS help files (xpdf.hlp, etc.).
+
+All of these utilities read an optional configuration file: see the
+xpdfrc(5) man page.
+
+
+Upgrading from Xpdf 3.02 (and earlier)
+--------------------------------------
+
+The font configuration system has been changed. Previous versions
+used mostly separate commands to configure fonts for display and for
+PostScript output. As of 3.03, configuration options that make sense
+for both display and PS output have been unified.
+The following xpdfrc commands have been removed:
+* displayFontT1, displayFontTT: replaced with fontFile
+* displayNamedCIDFontT1, displayNamedCIDFontTT: replaced with fontFile
+* displayCIDFontT1, displayCIDFontTT: replaced with fontFileCC
+* psFont: replaced with psResidentFont
+* psNamedFont16: replaced with psResidentFont16
+* psFont16: replaced with psResidentFontCC
-Upgrading from Xpdf 2.xx
-------------------------
+See the xpdfrc(5) man page for more information on the new commands.
-WARNING: Xpdf 3.00 switched to a new PDF rasterizer, which no longer
-uses X fonts. You'll need a set of Base-14 fonts -- the URW fonts
-distributed with ghostscript can be used for this. Xpdf will search
-for the URW fonts, but if you have them installed in a non-standard
-directory, you'll need to set up an xpdfrc config file to point to
-them. For full details, please see the xpdfrc(5) man page.
+Pdftops will now embed external 16-bit fonts (configured with the
+fontFileCC command) when the PDF file refers to a non-embedded font.
+It does not do any subsetting (yet), so the resulting PS files will be
+large.
Compiling Xpdf
diff --git a/aconf-dj.h b/aconf-dj.h
index fa92df3..24492df 100644
--- a/aconf-dj.h
+++ b/aconf-dj.h
@@ -46,6 +46,7 @@
#define HAVE_POPEN 1
#undef HAVE_MKSTEMP
#undef SELECT_TAKES_INT
+#define HAVE_STD_SORT 1
#undef HAVE_FSEEK64
/*
diff --git a/aconf-win32.h b/aconf-win32.h
index 0bdc763..240d046 100644
--- a/aconf-win32.h
+++ b/aconf-win32.h
@@ -69,6 +69,7 @@
#undef HAVE_MKSTEMP
#undef HAVE_MKSTEMPS
#undef SELECT_TAKES_INT
+#define HAVE_STD_SORT 1
#undef HAVE_FSEEKO
#undef HAVE_FSEEK64
#undef _FILE_OFFSET_BITS
diff --git a/aconf.h.in b/aconf.h.in
index b6c6351..42c04d8 100644
--- a/aconf.h.in
+++ b/aconf.h.in
@@ -69,6 +69,7 @@
#undef HAVE_MKSTEMP
#undef HAVE_MKSTEMPS
#undef SELECT_TAKES_INT
+#undef HAVE_STD_SORT
#undef HAVE_FSEEKO
#undef HAVE_FSEEK64
#undef _FILE_OFFSET_BITS
diff --git a/configure b/configure
index 121e7b2..03cd2de 100755
--- a/configure
+++ b/configure
@@ -1,81 +1,415 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
+# Generated by GNU Autoconf 2.65.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+#
#
-# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
fi
-DUALCASE=1; export DUALCASE # for MKS sh
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
fi
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_unset $as_var
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
-done
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
-# Name of the executable.
-as_me=`$as_basename "$0" ||
+as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
-
-# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
@@ -83,146 +417,107 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
+ s/-\n.*//
' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
# Exit status is that of the last command.
exit
}
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
esac
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
else
- as_expr=false
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
else
as_ln_s='cp -p'
fi
-rm -f conf$$ conf$$.exe conf$$.file
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
+ as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
-as_executable_p="test -f"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -231,38 +526,25 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
# Name of the host.
# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-exec 6>&1
-
#
# Initializations.
#
ac_default_prefix=/usr/local
+ac_clean_files=
ac_config_libobj_dir=.
+LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete. It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
# Identity of this package.
PACKAGE_NAME=
@@ -270,51 +552,182 @@ PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=
+PACKAGE_URL=
-ac_unique_file="xpdf/xpdf.cc"
+ac_unique_file="xpdf/Gfx.cc"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
-#if HAVE_SYS_TYPES_H
+#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_STAT_H
+#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
-# if HAVE_STDLIB_H
+# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
-#if HAVE_STRINGS_H
+#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
-#if HAVE_INTTYPES_H
+#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
#endif
-#if HAVE_UNISTD_H
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB EXE LIBPREFIX AR UP_DIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS EGREP Xpm_LIBS Xpm_CFLAGS Xext_LIBS Xext_CFLAGS Xp_LIBS Xp_CFLAGS Xt_LIBS Xt_CFLAGS Xm_LIBS Xm_CFLAGS Sgm_LIBS Sgm_CFLAGS t1_LIBS t1_CFLAGS freetype2_LIBS freetype2_CFLAGS libpaper_LIBS libpaper_CFLAGS X XPDF_TARGET LIBOBJS LTLIBOBJS'
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+XPDF_TARGET
+X
+libpaper_CFLAGS
+libpaper_LIBS
+freetype2_CFLAGS
+freetype2_LIBS
+t1_CFLAGS
+t1_LIBS
+Sgm_CFLAGS
+Sgm_LIBS
+Xm_CFLAGS
+Xm_LIBS
+Xt_CFLAGS
+Xt_LIBS
+Xp_CFLAGS
+Xp_LIBS
+Xext_CFLAGS
+Xext_LIBS
+Xpm_CFLAGS
+Xpm_LIBS
+EGREP
+GREP
+X_EXTRA_LIBS
+X_LIBS
+X_PRE_LIBS
+X_CFLAGS
+CPP
+XMKMF
+UP_DIR
+AR
+LIBPREFIX
+EXE
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_a4_paper
+enable_no_text_select
+enable_opi
+enable_multithreaded
+enable_exceptions
+enable_wordlist
+enable_fixedpoint
+enable_cmyk
+with_appdef_dir
+with_x
+enable_largefile
+with_Xpm_library
+with_Xpm_includes
+with_Xext_library
+with_Xext_includes
+with_Xp_library
+with_Xp_includes
+with_Xt_library
+with_Xt_includes
+with_Xm_library
+with_Xm_includes
+with_Sgm_library
+with_Sgm_includes
+with_freetype2_library
+with_freetype2_includes
+with_libpaper_library
+with_libpaper_includes
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+XMKMF
+CPP'
+
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
@@ -337,34 +750,48 @@ x_libraries=NONE
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
ac_prev=
+ac_dashdash=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
+ eval $ac_prev=\$ac_option
ac_prev=
continue
fi
- ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
# Accept the important Cygnus configure options, so we can diagnose typos.
- case $ac_option in
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
@@ -386,33 +813,59 @@ do
--config-cache | -C)
cache_file=config.cache ;;
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ -datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
datadir=$ac_optarg ;;
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
-disable-* | --disable-*)
- ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- eval "enable_$ac_feature=no" ;;
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
-enable-* | --enable-*)
- ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
esac
- eval "enable_$ac_feature='$ac_optarg'" ;;
+ eval enable_$ac_useropt=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -439,6 +892,12 @@ do
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
@@ -463,13 +922,16 @@ do
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
-localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
+ | --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
@@ -534,6 +996,16 @@ do
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
@@ -584,26 +1056,36 @@ do
ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
esac
- eval "with_$ac_package='$ac_optarg'" ;;
+ eval with_$ac_useropt=\$ac_optarg ;;
-without-* | --without-*)
- ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/-/_/g'`
- eval "with_$ac_package=no" ;;
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
--x)
# Obsolete; use --with-x.
@@ -623,26 +1105,25 @@ do
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
- -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; }
+ -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
- expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
- { (exit 1); exit 1; }; }
- ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
- eval "$ac_envvar='$ac_optarg'"
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
- echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
: ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
@@ -651,31 +1132,36 @@ done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- { echo "$as_me: error: missing argument to $ac_option" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error "missing argument to $ac_option"
fi
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
- eval ac_val=$`echo $ac_var`
- case $ac_val in
- [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
-done
+fi
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
- localstatedir libdir includedir oldincludedir infodir mandir
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
do
- eval ac_val=$`echo $ac_var`
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
case $ac_val in
- [\\/$]* | ?:[\\/]* ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
+ as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
@@ -689,7 +1175,7 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
- echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
If a cross compiler is detected then cross compile mode will be used." >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
@@ -702,82 +1188,72 @@ test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error "pwd does not report name of working directory"
+
+
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$0" : 'X\(//\)[^/]' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$0" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
+ if test ! -r "$srcdir/$ac_unique_file"; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
- { (exit 1); exit 1; }; }
- fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
- { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
- { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-ac_env_CXX_set=${CXX+set}
-ac_env_CXX_value=$CXX
-ac_cv_env_CXX_set=${CXX+set}
-ac_cv_env_CXX_value=$CXX
-ac_env_CXXFLAGS_set=${CXXFLAGS+set}
-ac_env_CXXFLAGS_value=$CXXFLAGS
-ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
-ac_cv_env_CXXFLAGS_value=$CXXFLAGS
-ac_env_CPP_set=${CPP+set}
-ac_env_CPP_value=$CPP
-ac_cv_env_CPP_set=${CPP+set}
-ac_cv_env_CPP_value=$CPP
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
#
# Report the --help message.
@@ -806,14 +1282,11 @@ Configuration:
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or \`..']
-_ACEOF
-
- cat <<_ACEOF
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
+ [$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
+ [PREFIX]
By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
@@ -823,18 +1296,25 @@ for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --infodir=DIR info documentation [PREFIX/info]
- --mandir=DIR man documentation [PREFIX/man]
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
_ACEOF
cat <<\_ACEOF
@@ -850,6 +1330,7 @@ if test -n "$ac_init_help"; then
cat <<\_ACEOF
Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-a4-paper use A4 paper size instead of Letter for
@@ -868,22 +1349,30 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-appdef-dir set app-defaults directory
--with-x use the X Window System
- --with-Xpm-library=PATH use Xpm library (pixmap library - used only for icon)
- --with-Xpm-includes=DIR set directory for Xpm headers
+ --with-Xpm-library=PATH
+ use Xpm library (pixmap library - used only for icon)
+ --with-Xpm-includes=DIR
+ set directory for Xpm headers
--with-Xext-library=PATH
use Xext library (Motif library)
--with-Xext-includes=DIR
set directory for Xext headers
- --with-Xp-library=PATH use Xp library (Motif library)
- --with-Xp-includes=DIR set directory for Xp headers
- --with-Xt-library=PATH use Xt library (Motif library)
- --with-Xt-includes=DIR set directory for Xt headers
- --with-Xm-library=PATH use Xm library (Motif library)
- --with-Xm-includes=DIR set directory for Xm headers
- --with-Sgm-library=PATH use Sgm library (SGI Motif library)
- --with-Sgm-includes=DIR set directory for Sgm headers
- --with-t1-library=PATH use t1 library (Type 1 font rasterizer)
- --with-t1-includes=DIR set directory for t1 headers
+ --with-Xp-library=PATH
+ use Xp library (Motif library)
+ --with-Xp-includes=DIR
+ set directory for Xp headers
+ --with-Xt-library=PATH
+ use Xt library (Motif library)
+ --with-Xt-includes=DIR
+ set directory for Xt headers
+ --with-Xm-library=PATH
+ use Xm library (Motif library)
+ --with-Xm-includes=DIR
+ set directory for Xm headers
+ --with-Sgm-library=PATH
+ use Sgm library (SGI Motif library)
+ --with-Sgm-includes=DIR
+ set directory for Sgm headers
--with-freetype2-library=PATH
use freetype2 library (FreeType2 font rasterizer - version 2.0.5+)
--with-freetype2-includes=DIR
@@ -898,128 +1387,603 @@ Some influential environment variables:
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
- CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
- headers in a nonstandard directory <include dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
CXX C++ compiler command
CXXFLAGS C++ compiler flags
+ XMKMF Path to xmkmf, Makefile generator for X Window System
CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
+Report bugs to the package provider.
_ACEOF
+ac_status=$?
fi
if test "$ac_init_help" = "recursive"; then
# If there are subdirs, report their specific --help.
- ac_popdir=`pwd`
for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d $ac_dir || continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
ac_builddir=.
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
case $srcdir in
- .) # No --srcdir option. We are building in place.
+ .) # We are building in place.
ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
- cd $ac_dir
- # Check for guested configure; otherwise get Cygnus style configure.
- if test -f $ac_srcdir/configure.gnu; then
- echo
- $SHELL $ac_srcdir/configure.gnu --help=recursive
- elif test -f $ac_srcdir/configure; then
- echo
- $SHELL $ac_srcdir/configure --help=recursive
- elif test -f $ac_srcdir/configure.ac ||
- test -f $ac_srcdir/configure.in; then
- echo
- $ac_configure --help
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
else
- echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi
- cd $ac_popdir
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
done
fi
-test -n "$ac_init_help" && exit 0
+test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.65
-Copyright (C) 2003 Free Software Foundation, Inc.
+Copyright (C) 2009 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
- exit 0
+ exit
fi
-exec 5>config.log
-cat >&5 <<_ACEOF
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_cxx_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.59. Invocation command line was
+generated by GNU Autoconf 2.65. Invocation command line was
$ $0 $@
_ACEOF
+exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
@@ -1038,7 +2002,7 @@ uname -v = `(uname -v) 2>/dev/null || echo unknown`
/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
@@ -1050,8 +2014,9 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- echo "PATH: $as_dir"
-done
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
} >&5
@@ -1073,7 +2038,6 @@ _ACEOF
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
-ac_sep=
ac_must_keep_next=false
for ac_pass in 1 2
do
@@ -1084,13 +2048,13 @@ do
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
- 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
- ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
@@ -1106,21 +2070,19 @@ do
-* ) ac_must_keep_next=true ;;
esac
fi
- ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
- # Get rid of the leading space.
- ac_sep=" "
+ as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
# Save into config.log some information that might help in debugging.
{
@@ -1133,20 +2095,35 @@ trap 'exit_status=$?
_ASBOX
echo
# The following way of writing the cache mishandles newlines in values,
-{
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
(set) 2>&1 |
- case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
sed -n \
- "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
- ;;
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
*)
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
- esac;
-}
+ esac |
+ sort
+)
echo
cat <<\_ASBOX
@@ -1157,22 +2134,28 @@ _ASBOX
echo
for ac_var in $ac_subst_vars
do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
_ASBOX
echo
for ac_var in $ac_subst_files
do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
@@ -1184,26 +2167,26 @@ _ASBOX
## ----------- ##
_ASBOX
echo
- sed "/^$/d" confdefs.h | sort
+ cat confdefs.h
echo
fi
test "$ac_signal" != 0 &&
- echo "$as_me: caught signal $ac_signal"
- echo "$as_me: exit $exit_status"
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
} >&5
- rm -f core *.core &&
- rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
- ' 0
+' 0
for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
@@ -1211,112 +2194,128 @@ cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
- { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
- [\\/]* | ?:[\\/]* ) . $cache_file;;
- *) . ./$cache_file;;
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
esac
fi
else
- { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
- sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+for ac_var in $ac_precious_vars; do
eval ac_old_set=\$ac_cv_env_${ac_var}_set
eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val="\$ac_cv_env_${ac_var}_value"
- eval ac_new_val="\$ac_env_${ac_var}_value"
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
if test "x$ac_old_val" != "x$ac_new_val"; then
- { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
-echo "$as_me: former value: $ac_old_val" >&2;}
- { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
-echo "$as_me: current value: $ac_new_val" >&2;}
- ac_cache_corrupted=:
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
- { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
- { (exit 1); exit 1; }; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -1325,99 +2324,66 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ac_config_headers="$ac_config_headers aconf.h"
+# Check whether --enable-a4-paper was given.
+if test "${enable_a4_paper+set}" = set; then :
+ enableval=$enable_a4_paper; $as_echo "#define A4_PAPER 1" >>confdefs.h
+fi
+# Check whether --enable-no-text-select was given.
+if test "${enable_no_text_select+set}" = set; then :
+ enableval=$enable_no_text_select; $as_echo "#define NO_TEXT_SELECT 1" >>confdefs.h
+fi
+# Check whether --enable-opi was given.
+if test "${enable_opi+set}" = set; then :
+ enableval=$enable_opi; $as_echo "#define OPI_SUPPORT 1" >>confdefs.h
+fi
+# Check whether --enable-multithreaded was given.
+if test "${enable_multithreaded+set}" = set; then :
+ enableval=$enable_multithreaded; $as_echo "#define MULTITHREADED 1" >>confdefs.h
+fi
+# Check whether --enable-exceptions was given.
+if test "${enable_exceptions+set}" = set; then :
+ enableval=$enable_exceptions; $as_echo "#define USE_EXCEPTIONS 1" >>confdefs.h
+fi
+# Check whether --enable-wordlist was given.
+if test "${enable_wordlist+set}" = set; then :
+ enableval=$enable_wordlist; $as_echo "#define TEXTOUT_WORD_LIST 1" >>confdefs.h
+fi
+# Check whether --enable-fixedpoint was given.
+if test "${enable_fixedpoint+set}" = set; then :
+ enableval=$enable_fixedpoint; $as_echo "#define USE_FIXEDPOINT 1" >>confdefs.h
+fi
+# Check whether --enable-cmyk was given.
+if test "${enable_cmyk+set}" = set; then :
+ enableval=$enable_cmyk; $as_echo "#define SPLASH_CMYK 1" >>confdefs.h
- ac_config_headers="$ac_config_headers aconf.h"
-
-
-# Check whether --enable-a4-paper or --disable-a4-paper was given.
-if test "${enable_a4_paper+set}" = set; then
- enableval="$enable_a4_paper"
- cat >>confdefs.h <<\_ACEOF
-#define A4_PAPER 1
-_ACEOF
-
-fi;
-# Check whether --enable-no-text-select or --disable-no-text-select was given.
-if test "${enable_no_text_select+set}" = set; then
- enableval="$enable_no_text_select"
- cat >>confdefs.h <<\_ACEOF
-#define NO_TEXT_SELECT 1
-_ACEOF
-
-fi;
-# Check whether --enable-opi or --disable-opi was given.
-if test "${enable_opi+set}" = set; then
- enableval="$enable_opi"
- cat >>confdefs.h <<\_ACEOF
-#define OPI_SUPPORT 1
-_ACEOF
-
-fi;
-# Check whether --enable-multithreaded or --disable-multithreaded was given.
-if test "${enable_multithreaded+set}" = set; then
- enableval="$enable_multithreaded"
- cat >>confdefs.h <<\_ACEOF
-#define MULTITHREADED 1
-_ACEOF
-
-fi;
-# Check whether --enable-exceptions or --disable-exceptions was given.
-if test "${enable_exceptions+set}" = set; then
- enableval="$enable_exceptions"
- cat >>confdefs.h <<\_ACEOF
-#define USE_EXCEPTIONS 1
-_ACEOF
-
-fi;
-# Check whether --enable-wordlist or --disable-wordlist was given.
-if test "${enable_wordlist+set}" = set; then
- enableval="$enable_wordlist"
- cat >>confdefs.h <<\_ACEOF
-#define TEXTOUT_WORD_LIST 1
-_ACEOF
-
-fi;
-# Check whether --enable-fixedpoint or --disable-fixedpoint was given.
-if test "${enable_fixedpoint+set}" = set; then
- enableval="$enable_fixedpoint"
- cat >>confdefs.h <<\_ACEOF
-#define USE_FIXEDPOINT 1
-_ACEOF
-
-fi;
-# Check whether --enable-cmyk or --disable-cmyk was given.
-if test "${enable_cmyk+set}" = set; then
- enableval="$enable_cmyk"
- cat >>confdefs.h <<\_ACEOF
-#define SPLASH_CMYK 1
-_ACEOF
+fi
-fi;
-# Check whether --with-appdef-dir or --without-appdef-dir was given.
-if test "${with_appdef_dir+set}" = set; then
- withval="$with_appdef_dir"
- cat >>confdefs.h <<_ACEOF
+# Check whether --with-appdef-dir was given.
+if test "${with_appdef_dir+set}" = set; then :
+ withval=$with_appdef_dir; cat >>confdefs.h <<_ACEOF
#define APPDEFDIR "$with_appdef_dir"
_ACEOF
-fi;
+fi
+
if test "$sysconfdir" = '${prefix}/etc'; then
if test "x$prefix" = xNONE; then
@@ -1441,10 +2407,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1454,35 +2420,37 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -1492,39 +2460,50 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
- CC=$ac_ct_CC
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1534,77 +2513,37 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- CC=$ac_ct_CC
-else
- CC="$ac_cv_prog_CC"
-fi
+ fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1615,18 +2554,19 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
@@ -1644,24 +2584,25 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
- for ac_prog in cl
+ for ac_prog in cl.exe
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1671,39 +2612,41 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
- for ac_prog in cl
+ for ac_prog in cl.exe
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -1713,66 +2656,78 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
test -n "$ac_ct_CC" && break
done
- CC=$ac_ct_CC
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
fi
fi
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
- "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -1784,112 +2739,109 @@ main ()
}
_ACEOF
ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
- (eval $ac_link_default) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Find the output, starting from the most likely. This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
- ;;
- conftest.$ac_ext )
- # This is the source file.
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
;;
[ab].out )
# We found the default executable, but exeext='' is most
# certainly right.
break;;
*.* )
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- # FIXME: I believe we export ac_cv_exeext for Libtool,
- # but it would be cool to find out if it's true. Does anybody
- # maintain Libtool? --akim.
- export ac_cv_exeext
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
break;;
* )
break;;
esac
done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
else
- echo "$as_me: failed program was:" >&5
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
fi
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
- fi
- fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -1897,38 +2849,90 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- export ac_cv_exeext
break;;
* ) break;;
esac
done
else
- { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -1940,45 +2944,46 @@ main ()
}
_ACEOF
rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else
- echo "$as_me: failed program was:" >&5
+ $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
fi
-
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -1992,55 +2997,34 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
+ ac_compiler_gnu=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2051,39 +3035,49 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
-ac_cv_prog_cc_g=no
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
@@ -2099,18 +3093,14 @@ else
CFLAGS=
fi
fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- ac_cv_prog_cc_stdc=no
+ ac_cv_prog_cc_c89=no
ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
#include <stdio.h>
@@ -2138,12 +3128,17 @@ static char *f (char * (*g) (char **, int), char **p, ...)
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not '\xHH' hex character constants.
These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std1 is added to get
+ as 'x'. The following induces an error, until -std is added to get
proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std1. */
+ that's true only with -std. */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
@@ -2158,205 +3153,37 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
return 0;
}
_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX 10.20 and later -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_stdc=$ac_arg
-break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
done
-rm -f conftest.$ac_ext conftest.$ac_objext
+rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
-
-case "x$ac_cv_prog_cc_stdc" in
- x|xno)
- echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
*)
- echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
- CC="$CC $ac_cv_prog_cc_stdc" ;;
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
-# Some people use a C++ compiler to compile C. Since we use `exit',
-# in C++ we need to declare it. In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
- choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- for ac_declaration in \
- '' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2364,150 +3191,376 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking for library containing strerror" >&5
-echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6
-if test "${ac_cv_search_strerror+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5
+$as_echo_n "checking for library containing strerror... " >&6; }
+if test "${ac_cv_search_strerror+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-ac_cv_search_strerror=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char strerror ();
int
main ()
{
-strerror ();
+return strerror ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_strerror="none required"
+for ac_lib in '' cposix; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_strerror=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_strerror+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_strerror+set}" = set; then :
+
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ ac_cv_search_strerror=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5
+$as_echo "$ac_cv_search_strerror" >&6; }
+ac_res=$ac_cv_search_strerror
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test "$ac_cv_search_strerror" = no; then
- for ac_lib in cposix; do
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+
+ case $ac_cv_prog_cc_stdc in #(
+ no) :
+ ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #(
+ *) :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
+$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
+if test "${ac_cv_prog_cc_c99+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strerror ();
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+}
+
int
main ()
{
-strerror ();
+
+ // Check bool.
+ _Bool success = false;
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
+
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_strerror="-l$ac_lib"
-break
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -xc99=all -qlanglvl=extc99
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c99"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c99" != xno; then :
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- done
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
fi
-LIBS=$ac_func_search_save_LIBS
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+else
+ ac_cv_prog_cc_stdc=no
fi
-echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5
-echo "${ECHO_T}$ac_cv_search_strerror" >&6
-if test "$ac_cv_search_strerror" != no; then
- test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS"
fi
-
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5
+$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; }
+ if test "${ac_cv_prog_cc_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+fi
+
+ case $ac_cv_prog_cc_stdc in #(
+ no) :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;; #(
+ '') :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;; #(
+ *) :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5
+$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;;
+esac
#if test -z "$CXX" -a "$CC" = "gcc"; then
# CXX="gcc"
#fi
-ac_ext=cc
+ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
@@ -2517,39 +3570,41 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
- echo "$as_me:$LINENO: result: $CXX" >&5
-echo "${ECHO_T}$CXX" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
test -n "$CXX" && break
done
fi
if test -z "$CXX"; then
ac_ct_CXX=$CXX
- for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CXX"; then
ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
@@ -2559,64 +3614,77 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CXX="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
if test -n "$ac_ct_CXX"; then
- echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
-echo "${ECHO_T}$ac_ct_CXX" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
test -n "$ac_ct_CXX" && break
done
-test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
- CXX=$ac_ct_CXX
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
fi
-
+ fi
+fi
# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
- "checking for C++ compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
-echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2630,55 +3698,34 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
+ ac_compiler_gnu=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
fi
-echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
-GXX=`test $ac_compiler_gnu = yes && echo yes`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
ac_test_CXXFLAGS=${CXXFLAGS+set}
ac_save_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
-echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cxx_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2689,160 +3736,64 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
ac_cv_prog_cxx_g=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cxx_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
-if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
- if test "$GXX" = yes; then
- CXXFLAGS="-g -O2"
- else
- CXXFLAGS="-g"
- fi
-else
- if test "$GXX" = yes; then
- CXXFLAGS="-O2"
- else
- CXXFLAGS=
- fi
-fi
-for ac_declaration in \
- '' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-$ac_declaration
-#include <stdlib.h>
+
int
main ()
{
-exit (42);
+
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_cxx_try_compile "$LINENO"; then :
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-$ac_declaration
+
int
main ()
{
-exit (42);
+
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
fi
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2850,29 +3801,27 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f $ac_dir/shtool; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ for ac_t in install-sh install.sh shtool; do
+ if test -f "$ac_dir/$ac_t"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/$ac_t -c"
+ break 2
+ fi
+ done
done
if test -z "$ac_aux_dir"; then
- { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
-echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
fi
-ac_config_guess="$SHELL $ac_aux_dir/config.guess"
-ac_config_sub="$SHELL $ac_aux_dir/config.sub"
-ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
@@ -2887,22 +3836,23 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
-echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
-echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+if test "${ac_cv_path_install+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
- ./ | .// | /cC/* | \
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
@@ -2910,7 +3860,7 @@ case $as_dir/ in
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
@@ -2920,30 +3870,43 @@ case $as_dir/ in
# program-specific install script used by HP pwplus--don't use.
:
else
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
fi
fi
done
done
;;
esac
-done
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
fi
if test "${ac_cv_path_install+set}" = set; then
INSTALL=$ac_cv_path_install
else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
- # removed, or if the path is relative.
+ # removed, or if the value is a relative name.
INSTALL=$ac_install_sh
fi
fi
-echo "$as_me:$LINENO: result: $INSTALL" >&5
-echo "${ECHO_T}$INSTALL" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
@@ -2956,10 +3919,10 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
@@ -2969,35 +3932,37 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
fi
if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
@@ -3007,28 +3972,38 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
+IFS=$as_save_IFS
- test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
- RANLIB=$ac_ct_RANLIB
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
else
RANLIB="$ac_cv_prog_RANLIB"
fi
@@ -3039,16 +4014,12 @@ LIBPREFIX="lib"
AR="ar rc"
UP_DIR=""
-echo "$as_me:$LINENO: checking for OS/2 (with EMX)" >&5
-echo $ECHO_N "checking for OS/2 (with EMX)... $ECHO_C" >&6
-if test "${xpdf_cv_sys_os2+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OS/2 (with EMX)" >&5
+$as_echo_n "checking for OS/2 (with EMX)... " >&6; }
+if test "${xpdf_cv_sys_os2+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3059,55 +4030,27 @@ __EMX__
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
xpdf_cv_sys_os2=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_cv_sys_os2=no
+ xpdf_cv_sys_os2=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $xpdf_cv_sys_os2" >&5
-echo "${ECHO_T}$xpdf_cv_sys_os2" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_sys_os2" >&5
+$as_echo "$xpdf_cv_sys_os2" >&6; }
if test "$xpdf_cv_sys_os2" = yes; then
EXE=".exe"
LIBPREFIX=""
AR="ar -rc"
fi
-echo "$as_me:$LINENO: checking for DOS (with DJGPP)" >&5
-echo $ECHO_N "checking for DOS (with DJGPP)... $ECHO_C" >&6
-if test "${xpdf_cv_sys_dos+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DOS (with DJGPP)" >&5
+$as_echo_n "checking for DOS (with DJGPP)... " >&6; }
+if test "${xpdf_cv_sys_dos+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3118,39 +4061,15 @@ __DJGPP__
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
xpdf_cv_sys_dos=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_cv_sys_dos=no
+ xpdf_cv_sys_dos=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $xpdf_cv_sys_dos" >&5
-echo "${ECHO_T}$xpdf_cv_sys_dos" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_sys_dos" >&5
+$as_echo "$xpdf_cv_sys_dos" >&6; }
if test "$xpdf_cv_sys_dos" = yes; then
EXE=".exe"
LIBPREFIX="lib"
@@ -3168,15 +4087,15 @@ ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ if test "${ac_cv_prog_CPP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
# Double quotes because CPP needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
@@ -3190,11 +4109,7 @@ do
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
@@ -3203,68 +4118,24 @@ cat >>conftest.$ac_ext <<_ACEOF
#endif
Syntax error
_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
+else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
- # OK, works on sane cases. Now check whether non-existent headers
+ # OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
# Passes both tests.
ac_preproc_ok=:
break
@@ -3274,7 +4145,7 @@ rm -f conftest.err conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
+if $ac_preproc_ok; then :
break
fi
@@ -3286,8 +4157,8 @@ fi
else
ac_cv_prog_CPP=$CPP
fi
-echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
@@ -3297,11 +4168,7 @@ do
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
@@ -3310,68 +4177,24 @@ cat >>conftest.$ac_ext <<_ACEOF
#endif
Syntax error
_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
+else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
- # OK, works on sane cases. Now check whether non-existent headers
+ # OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
# Passes both tests.
ac_preproc_ok=:
break
@@ -3381,14 +4204,13 @@ rm -f conftest.err conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
+if $ac_preproc_ok; then :
+
else
- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
fi
ac_ext=c
@@ -3398,44 +4220,47 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking for X" >&5
-echo $ECHO_N "checking for X... $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5
+$as_echo_n "checking for X... " >&6; }
-# Check whether --with-x or --without-x was given.
-if test "${with_x+set}" = set; then
- withval="$with_x"
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then :
+ withval=$with_x;
+fi
-fi;
# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
if test "x$with_x" = xno; then
# The user explicitly disabled X.
have_x=disabled
else
- if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
- # Both variables are already set.
- have_x=yes
- else
- if test "${ac_cv_have_x+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ case $x_includes,$x_libraries in #(
+ *\'*) as_fn_error "cannot use X directory names containing '" "$LINENO" 5;; #(
+ *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
# One or both of the vars are not set, and there is no cached value.
ac_x_includes=no ac_x_libraries=no
-rm -fr conftest.dir
+rm -f -r conftest.dir
if mkdir conftest.dir; then
cd conftest.dir
- # Make sure to not put "make" in the Imakefile rules, since we grep it out.
cat >Imakefile <<'_ACEOF'
-acfindx:
- @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
-_ACEOF
- if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+incroot:
+ @echo incroot='${INCROOT}'
+usrlibdir:
+ @echo usrlibdir='${USRLIBDIR}'
+libdir:
+ @echo libdir='${LIBDIR}'
+_ACEOF
+ if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
- eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ for ac_var in incroot usrlibdir libdir; do
+ eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+ done
# Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
- for ac_extension in a so sl; do
- if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
- test -f $ac_im_libdir/libX11.$ac_extension; then
+ for ac_extension in a so sl dylib la dll; do
+ if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+ test -f "$ac_im_libdir/libX11.$ac_extension"; then
ac_im_usrlibdir=$ac_im_libdir; break
fi
done
@@ -3443,37 +4268,41 @@ _ACEOF
# bogus both because they are the default anyway, and because
# using them would break gcc on systems where it needs fixed includes.
case $ac_im_incroot in
- /usr/include) ;;
+ /usr/include) ac_x_includes= ;;
*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
esac
case $ac_im_usrlibdir in
- /usr/lib | /lib) ;;
+ /usr/lib | /usr/lib64 | /lib | /lib64) ;;
*) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
esac
fi
cd ..
- rm -fr conftest.dir
+ rm -f -r conftest.dir
fi
# Standard set of common directories for X headers.
# Check X11 before X11Rn because it is often a symlink to the current release.
ac_x_header_dirs='
/usr/X11/include
+/usr/X11R7/include
/usr/X11R6/include
/usr/X11R5/include
/usr/X11R4/include
/usr/include/X11
+/usr/include/X11R7
/usr/include/X11R6
/usr/include/X11R5
/usr/include/X11R4
/usr/local/X11/include
+/usr/local/X11R7/include
/usr/local/X11R6/include
/usr/local/X11R5/include
/usr/local/X11R4/include
/usr/local/include/X11
+/usr/local/include/X11R7
/usr/local/include/X11R6
/usr/local/include/X11R5
/usr/local/include/X11R4
@@ -3493,42 +4322,18 @@ ac_x_header_dirs='
/usr/openwin/share/include'
if test "$ac_x_includes" = no; then
- # Guess where to find include files, by looking for Intrinsic.h.
+ # Guess where to find include files, by looking for Xlib.h.
# First, try using that file with no special directory specified.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+if ac_fn_c_try_cpp "$LINENO"; then :
# We can compile using X headers with no special include directory.
ac_x_includes=
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
for ac_dir in $ac_x_header_dirs; do
- if test -r "$ac_dir/X11/Intrinsic.h"; then
+ if test -r "$ac_dir/X11/Xlib.h"; then
ac_x_includes=$ac_dir
break
fi
@@ -3542,102 +4347,76 @@ if test "$ac_x_libraries" = no; then
# See if we find them without any special options.
# Don't add to $LIBS permanently.
ac_save_LIBS=$LIBS
- LIBS="-lXt $LIBS"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ LIBS="-lX11 $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
int
main ()
{
-XtMalloc (0)
+XrmInitialize ()
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
LIBS=$ac_save_LIBS
# We can link X programs with no special library path.
ac_x_libraries=
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-LIBS=$ac_save_LIBS
-for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+ LIBS=$ac_save_LIBS
+for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
do
# Don't even attempt the hair of trying to link an X program!
- for ac_extension in a so sl; do
- if test -r $ac_dir/libXt.$ac_extension; then
+ for ac_extension in a so sl dylib la dll; do
+ if test -r "$ac_dir/libX11.$ac_extension"; then
ac_x_libraries=$ac_dir
break 2
fi
done
done
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi # $ac_x_libraries = no
-if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then
- # Didn't find X anywhere. Cache the known absence of X.
- ac_cv_have_x="have_x=no"
-else
- # Record where we found X for the cache.
- ac_cv_have_x="have_x=yes \
- ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
-fi
+case $ac_x_includes,$ac_x_libraries in #(
+ no,* | *,no | *\'*)
+ # Didn't find X, or a directory has "'" in its name.
+ ac_cv_have_x="have_x=no";; #(
+ *)
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$ac_x_includes'\
+ ac_x_libraries='$ac_x_libraries'"
+esac
fi
-
- fi
+;; #(
+ *) have_x=yes;;
+ esac
eval "$ac_cv_have_x"
fi # $with_x != no
if test "$have_x" != yes; then
- echo "$as_me:$LINENO: result: $have_x" >&5
-echo "${ECHO_T}$have_x" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5
+$as_echo "$have_x" >&6; }
no_x=yes
else
# If each of the values was on the command line, it overrides each guess.
test "x$x_includes" = xNONE && x_includes=$ac_x_includes
test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
# Update the cache value to reflect the command line values.
- ac_cv_have_x="have_x=yes \
- ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
- echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5
-echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$x_includes'\
+ ac_x_libraries='$x_libraries'"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5
+$as_echo "libraries $x_libraries, headers $x_includes" >&6; }
fi
if test "$no_x" = yes; then
# Not all programs may use this symbol, but it does not hurt to define it.
-cat >>confdefs.h <<\_ACEOF
-#define X_DISPLAY_MISSING 1
-_ACEOF
+$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h
X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
else
@@ -3650,16 +4429,12 @@ else
X_LIBS="$X_LIBS -L$x_libraries"
# For Solaris; some versions of Sun CC require a space after -R and
# others require no space. Words are not sufficient . . . .
- case `(uname -sr) 2>/dev/null` in
- "SunOS 5"*)
- echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5
-echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6
- ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5
+$as_echo_n "checking whether -R must be followed by a space... " >&6; }
+ ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
+ ac_xsave_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3670,48 +4445,13 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_R_nospace=yes
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ X_LIBS="$X_LIBS -R$x_libraries"
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_R_nospace=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- if test $ac_R_nospace = yes; then
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
- X_LIBS="$X_LIBS -R$x_libraries"
- else
- LIBS="$ac_xsave_LIBS -R $x_libraries"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3722,48 +4462,21 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_R_space=yes
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ X_LIBS="$X_LIBS -R $x_libraries"
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_R_space=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5
+$as_echo "neither works" >&6; }
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- if test $ac_R_space = yes; then
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- X_LIBS="$X_LIBS -R $x_libraries"
- else
- echo "$as_me:$LINENO: result: neither works" >&5
-echo "${ECHO_T}neither works" >&6
- fi
- fi
- LIBS=$ac_xsave_LIBS
- esac
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_c_werror_flag=$ac_xsave_c_werror_flag
+ LIBS=$ac_xsave_LIBS
fi
# Check for system-dependent libraries X programs must link with.
@@ -3777,196 +4490,112 @@ echo "${ECHO_T}neither works" >&6
# libraries were built with DECnet support. And Karl Berry says
# the Alpha needs dnet_stub (dnet does not exist).
ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XOpenDisplay ();
int
main ()
{
-XOpenDisplay ();
+return XOpenDisplay ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_link "$LINENO"; then :
-echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5
-echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6
-if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; }
+if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldnet $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char dnet_ntoa ();
int
main ()
{
-dnet_ntoa ();
+return dnet_ntoa ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dnet_dnet_ntoa=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dnet_dnet_ntoa=no
+ ac_cv_lib_dnet_dnet_ntoa=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
-echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6
-if test $ac_cv_lib_dnet_dnet_ntoa = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_dnet_ntoa" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
fi
if test $ac_cv_lib_dnet_dnet_ntoa = no; then
- echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5
-echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6
-if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; }
+if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldnet_stub $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char dnet_ntoa ();
int
main ()
{
-dnet_ntoa ();
+return dnet_ntoa ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dnet_stub_dnet_ntoa=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dnet_stub_dnet_ntoa=no
+ ac_cv_lib_dnet_stub_dnet_ntoa=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
-echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6
-if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
fi
fi
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS="$ac_xsave_LIBS"
# msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
@@ -3977,232 +4606,90 @@ rm -f conftest.err conftest.$ac_objext \
# on Irix 5.2, according to T.E. Dickey.
# The functions gethostbyname, getservbyname, and inet_addr are
# in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
- echo "$as_me:$LINENO: checking for gethostbyname" >&5
-echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6
-if test "${ac_cv_func_gethostbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define gethostbyname innocuous_gethostbyname
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gethostbyname (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef gethostbyname
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyname ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
-choke me
-#else
-char (*f) () = gethostbyname;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != gethostbyname;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_gethostbyname=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = x""yes; then :
-ac_cv_func_gethostbyname=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5
-echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6
if test $ac_cv_func_gethostbyname = no; then
- echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5
-echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6
-if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char gethostbyname ();
int
main ()
{
-gethostbyname ();
+return gethostbyname ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_nsl_gethostbyname=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_nsl_gethostbyname=no
+ ac_cv_lib_nsl_gethostbyname=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5
-echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6
-if test $ac_cv_lib_nsl_gethostbyname = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
fi
if test $ac_cv_lib_nsl_gethostbyname = no; then
- echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5
-echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6
-if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
+$as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
+if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lbsd $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char gethostbyname ();
int
main ()
{
-gethostbyname ();
+return gethostbyname ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_bsd_gethostbyname=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_bsd_gethostbyname=no
+ ac_cv_lib_bsd_gethostbyname=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5
-echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6
-if test $ac_cv_lib_bsd_gethostbyname = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
+$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
fi
@@ -4216,489 +4703,147 @@ fi
# variants that don't use the name server (or something). -lsocket
# must be given before -lnsl if both are needed. We assume that
# if connect needs -lnsl, so does gethostbyname.
- echo "$as_me:$LINENO: checking for connect" >&5
-echo $ECHO_N "checking for connect... $ECHO_C" >&6
-if test "${ac_cv_func_connect+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define connect to an innocuous variant, in case <limits.h> declares connect.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define connect innocuous_connect
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char connect (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef connect
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char connect ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_connect) || defined (__stub___connect)
-choke me
-#else
-char (*f) () = connect;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != connect;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_connect=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = x""yes; then :
-ac_cv_func_connect=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5
-echo "${ECHO_T}$ac_cv_func_connect" >&6
if test $ac_cv_func_connect = no; then
- echo "$as_me:$LINENO: checking for connect in -lsocket" >&5
-echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6
-if test "${ac_cv_lib_socket_connect+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
+$as_echo_n "checking for connect in -lsocket... " >&6; }
+if test "${ac_cv_lib_socket_connect+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char connect ();
int
main ()
{
-connect ();
+return connect ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_socket_connect=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_socket_connect=no
+ ac_cv_lib_socket_connect=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5
-echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6
-if test $ac_cv_lib_socket_connect = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5
+$as_echo "$ac_cv_lib_socket_connect" >&6; }
+if test "x$ac_cv_lib_socket_connect" = x""yes; then :
X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
fi
fi
# Guillermo Gomez says -lposix is necessary on A/UX.
- echo "$as_me:$LINENO: checking for remove" >&5
-echo $ECHO_N "checking for remove... $ECHO_C" >&6
-if test "${ac_cv_func_remove+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define remove to an innocuous variant, in case <limits.h> declares remove.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define remove innocuous_remove
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char remove (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
+ ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove"
+if test "x$ac_cv_func_remove" = x""yes; then :
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef remove
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char remove ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_remove) || defined (__stub___remove)
-choke me
-#else
-char (*f) () = remove;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != remove;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_remove=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_remove=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5
-echo "${ECHO_T}$ac_cv_func_remove" >&6
if test $ac_cv_func_remove = no; then
- echo "$as_me:$LINENO: checking for remove in -lposix" >&5
-echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6
-if test "${ac_cv_lib_posix_remove+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5
+$as_echo_n "checking for remove in -lposix... " >&6; }
+if test "${ac_cv_lib_posix_remove+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lposix $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char remove ();
int
main ()
{
-remove ();
+return remove ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_posix_remove=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_posix_remove=no
+ ac_cv_lib_posix_remove=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5
-echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6
-if test $ac_cv_lib_posix_remove = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5
+$as_echo "$ac_cv_lib_posix_remove" >&6; }
+if test "x$ac_cv_lib_posix_remove" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
fi
fi
# BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
- echo "$as_me:$LINENO: checking for shmat" >&5
-echo $ECHO_N "checking for shmat... $ECHO_C" >&6
-if test "${ac_cv_func_shmat+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define shmat to an innocuous variant, in case <limits.h> declares shmat.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define shmat innocuous_shmat
+ ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat"
+if test "x$ac_cv_func_shmat" = x""yes; then :
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char shmat (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef shmat
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shmat ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_shmat) || defined (__stub___shmat)
-choke me
-#else
-char (*f) () = shmat;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != shmat;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_shmat=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_shmat=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5
-echo "${ECHO_T}$ac_cv_func_shmat" >&6
if test $ac_cv_func_shmat = no; then
- echo "$as_me:$LINENO: checking for shmat in -lipc" >&5
-echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6
-if test "${ac_cv_lib_ipc_shmat+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5
+$as_echo_n "checking for shmat in -lipc... " >&6; }
+if test "${ac_cv_lib_ipc_shmat+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lipc $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char shmat ();
int
main ()
{
-shmat ();
+return shmat ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ipc_shmat=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_ipc_shmat=no
+ ac_cv_lib_ipc_shmat=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5
-echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6
-if test $ac_cv_lib_ipc_shmat = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5
+$as_echo "$ac_cv_lib_ipc_shmat" >&6; }
+if test "x$ac_cv_lib_ipc_shmat" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
fi
@@ -4714,71 +4859,43 @@ fi
# These have to be linked with before -lX11, unlike the other
# libraries we check for below, so use a different variable.
# John Interrante, Karl Berry
- echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5
-echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6
-if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5
+$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; }
+if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lICE $X_EXTRA_LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char IceConnectionNumber ();
int
main ()
{
-IceConnectionNumber ();
+return IceConnectionNumber ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ICE_IceConnectionNumber=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_ICE_IceConnectionNumber=no
+ ac_cv_lib_ICE_IceConnectionNumber=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
-echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6
-if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
+$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
+if test "x$ac_cv_lib_ICE_IceConnectionNumber" = x""yes; then :
X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
fi
@@ -4786,24 +4903,15 @@ fi
fi
-
-
-
-
-
ac_header_dirent=no
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
- as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
-echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <$ac_hdr>
@@ -4817,42 +4925,20 @@ return 0;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
eval "$as_ac_Header=yes"
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_Header=no"
+ eval "$as_ac_Header=no"
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+eval ac_res=\$$as_ac_Header
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
_ACEOF
ac_header_dirent=$ac_hdr; break
@@ -4861,263 +4947,123 @@ fi
done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
- echo "$as_me:$LINENO: checking for library containing opendir" >&5
-echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
-if test "${ac_cv_search_opendir+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-ac_cv_search_opendir=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char opendir ();
int
main ()
{
-opendir ();
+return opendir ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_opendir="none required"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test "$ac_cv_search_opendir" = no; then
- for ac_lib in dir; do
+for ac_lib in '' dir; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_opendir+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then :
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir ();
-int
-main ()
-{
-opendir ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_opendir="-l$ac_lib"
-break
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- done
+ ac_cv_search_opendir=no
fi
+rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
-echo "${ECHO_T}$ac_cv_search_opendir" >&6
-if test "$ac_cv_search_opendir" != no; then
- test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
else
- echo "$as_me:$LINENO: checking for library containing opendir" >&5
-echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
-if test "${ac_cv_search_opendir+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-ac_cv_search_opendir=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char opendir ();
int
main ()
{
-opendir ();
+return opendir ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_opendir="none required"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test "$ac_cv_search_opendir" = no; then
- for ac_lib in x; do
+for ac_lib in '' x; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_opendir+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then :
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir ();
-int
-main ()
-{
-opendir ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_search_opendir="-l$ac_lib"
-break
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- done
+ ac_cv_search_opendir=no
fi
+rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
-echo "${ECHO_T}$ac_cv_search_opendir" >&6
-if test "$ac_cv_search_opendir" != no; then
- test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
fi
-ac_ext=cc
+ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@@ -5125,175 +5071,57 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-echo "$as_me:$LINENO: checking for gethostbyname" >&5
-echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6
-if test "${ac_cv_func_gethostbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define gethostbyname innocuous_gethostbyname
+ac_fn_cxx_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = x""yes; then :
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gethostbyname (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef gethostbyname
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyname ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
-choke me
-#else
-char (*f) () = gethostbyname;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != gethostbyname;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_gethostbyname=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_gethostbyname=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5
-echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6
if test $ac_cv_func_gethostbyname = no; then
- echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5
-echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6
-if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
+$as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
+if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lbsd $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char gethostbyname ();
int
main ()
{
-gethostbyname ();
+return gethostbyname ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_bsd_gethostbyname=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_bsd_gethostbyname=no
+ ac_cv_lib_bsd_gethostbyname=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5
-echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6
-if test $ac_cv_lib_bsd_gethostbyname = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
+$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then :
X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
fi
fi
-echo "$as_me:$LINENO: checking select() and fd_set in sys/select.h and sys/bsdtypes.h" >&5
-echo $ECHO_N "checking select() and fd_set in sys/select.h and sys/bsdtypes.h... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking select() and fd_set in sys/select.h and sys/bsdtypes.h" >&5
+$as_echo_n "checking select() and fd_set in sys/select.h and sys/bsdtypes.h... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stddef.h>
@@ -5308,45 +5136,17 @@ select(0, NULL, NULL, NULL, NULL);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- echo "$as_me:$LINENO: result: not needed" >&5
-echo "${ECHO_T}not needed" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not needed" >&5
+$as_echo "not needed" >&6; }
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stddef.h>
@@ -5362,49 +5162,19 @@ select(0, NULL, NULL, NULL, NULL);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_SELECT_H 1
-_ACEOF
+ $as_echo "#define HAVE_SYS_SELECT_H 1" >>confdefs.h
- echo "$as_me:$LINENO: result: need sys/select.h" >&5
-echo "${ECHO_T}need sys/select.h" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: need sys/select.h" >&5
+$as_echo "need sys/select.h" >&6; }
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stddef.h>
@@ -5420,57 +5190,27 @@ select(0, NULL, NULL, NULL, NULL);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_BSDTYPES_H 1
-_ACEOF
+ $as_echo "#define HAVE_SYS_BSDTYPES_H 1" >>confdefs.h
- echo "$as_me:$LINENO: result: need sys/bsdtypes.h" >&5
-echo "${ECHO_T}need sys/bsdtypes.h" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: need sys/bsdtypes.h" >&5
+$as_echo "need sys/bsdtypes.h" >&6; }
else
- echo "$as_me:$LINENO: result: problem" >&5
-echo "${ECHO_T}problem" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: problem" >&5
+$as_echo "problem" >&6; }
fi
fi
fi
-echo "$as_me:$LINENO: checking FD_ZERO and strings.h or bstring.h" >&5
-echo $ECHO_N "checking FD_ZERO and strings.h or bstring.h... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking FD_ZERO and strings.h or bstring.h" >&5
+$as_echo_n "checking FD_ZERO and strings.h or bstring.h... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <sys/types.h>
@@ -5485,45 +5225,17 @@ fd_set fds; FD_ZERO(&fds);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- echo "$as_me:$LINENO: result: not needed" >&5
-echo "${ECHO_T}not needed" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not needed" >&5
+$as_echo "not needed" >&6; }
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <sys/types.h>
@@ -5539,49 +5251,19 @@ fd_set fds; FD_ZERO(&fds);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRINGS_H 1
-_ACEOF
+ $as_echo "#define HAVE_STRINGS_H 1" >>confdefs.h
- echo "$as_me:$LINENO: result: need strings.h" >&5
-echo "${ECHO_T}need strings.h" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: need strings.h" >&5
+$as_echo "need strings.h" >&6; }
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <sys/types.h>
@@ -5597,219 +5279,73 @@ fd_set fds; FD_ZERO(&fds);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_ok=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_ok=no
+ xpdf_ok=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $xpdf_ok = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_BSTRING_H 1
-_ACEOF
+ $as_echo "#define HAVE_BSTRING_H 1" >>confdefs.h
- echo "$as_me:$LINENO: result: need bstring.h" >&5
-echo "${ECHO_T}need bstring.h" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: need bstring.h" >&5
+$as_echo "need bstring.h" >&6; }
else
- echo "$as_me:$LINENO: result: problem" >&5
-echo "${ECHO_T}problem" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: problem" >&5
+$as_echo "problem" >&6; }
fi
fi
fi
-
for ac_func in rewinddir
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
+do :
+ ac_fn_cxx_check_func "$LINENO" "rewinddir" "ac_cv_func_rewinddir"
+if test "x$ac_cv_func_rewinddir" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_REWINDDIR 1
_ACEOF
fi
done
if test $ac_cv_func_rewinddir = no; then
-
-echo "$as_me:$LINENO: checking for rewinddir in -lcposix" >&5
-echo $ECHO_N "checking for rewinddir in -lcposix... $ECHO_C" >&6
-if test "${ac_cv_lib_cposix_rewinddir+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rewinddir in -lcposix" >&5
+$as_echo_n "checking for rewinddir in -lcposix... " >&6; }
+if test "${ac_cv_lib_cposix_rewinddir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcposix $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char rewinddir ();
int
main ()
{
-rewinddir ();
+return rewinddir ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_cposix_rewinddir=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_cposix_rewinddir=no
+ ac_cv_lib_cposix_rewinddir=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_cposix_rewinddir" >&5
-echo "${ECHO_T}$ac_cv_lib_cposix_rewinddir" >&6
-if test $ac_cv_lib_cposix_rewinddir = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cposix_rewinddir" >&5
+$as_echo "$ac_cv_lib_cposix_rewinddir" >&6; }
+if test "x$ac_cv_lib_cposix_rewinddir" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCPOSIX 1
_ACEOF
@@ -5820,118 +5356,23 @@ fi
fi
-
for ac_func in popen
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
+do :
+ ac_fn_cxx_check_func "$LINENO" "popen" "ac_cv_func_popen"
+if test "x$ac_cv_func_popen" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_POPEN 1
_ACEOF
fi
done
-echo "$as_me:$LINENO: checking for mkstemp" >&5
-echo $ECHO_N "checking for mkstemp... $ECHO_C" >&6
-if test "${xpdf_cv_func_mkstemp+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mkstemp" >&5
+$as_echo_n "checking for mkstemp... " >&6; }
+if test "${xpdf_cv_func_mkstemp+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <unistd.h>
@@ -5943,56 +5384,26 @@ mkstemp("foo");
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_link "$LINENO"; then :
xpdf_cv_func_mkstemp=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_cv_func_mkstemp=no
+ xpdf_cv_func_mkstemp=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $xpdf_cv_func_mkstemp" >&5
-echo "${ECHO_T}$xpdf_cv_func_mkstemp" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_func_mkstemp" >&5
+$as_echo "$xpdf_cv_func_mkstemp" >&6; }
if test "$xpdf_cv_func_mkstemp" = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_MKSTEMP 1
-_ACEOF
+ $as_echo "#define HAVE_MKSTEMP 1" >>confdefs.h
fi
-echo "$as_me:$LINENO: checking for mkstemps" >&5
-echo $ECHO_N "checking for mkstemps... $ECHO_C" >&6
-if test "${xpdf_cv_func_mkstemps+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mkstemps" >&5
+$as_echo_n "checking for mkstemps... " >&6; }
+if test "${xpdf_cv_func_mkstemps+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <unistd.h>
@@ -6004,57 +5415,27 @@ mkstemps("foo", 0);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_link "$LINENO"; then :
xpdf_cv_func_mkstemps=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_cv_func_mkstemps=no
+ xpdf_cv_func_mkstemps=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $xpdf_cv_func_mkstemps" >&5
-echo "${ECHO_T}$xpdf_cv_func_mkstemps" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_func_mkstemps" >&5
+$as_echo "$xpdf_cv_func_mkstemps" >&6; }
if test "$xpdf_cv_func_mkstemps" = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_MKSTEMPS 1
-_ACEOF
+ $as_echo "#define HAVE_MKSTEMPS 1" >>confdefs.h
fi
-echo "$as_me:$LINENO: checking whether select takes fd_set arguments" >&5
-echo $ECHO_N "checking whether select takes fd_set arguments... $ECHO_C" >&6
-if test "${xpdf_cv_func_select_arg+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether select takes fd_set arguments" >&5
+$as_echo_n "checking whether select takes fd_set arguments... " >&6; }
+if test "${xpdf_cv_func_select_arg+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/time.h>
@@ -6071,43 +5452,51 @@ select(1, &fds, &fds, &fds, 0);
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_cxx_try_compile "$LINENO"; then :
xpdf_cv_func_select_arg=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-xpdf_cv_func_select_arg=no
+ xpdf_cv_func_select_arg=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $xpdf_cv_func_select_arg" >&5
-echo "${ECHO_T}$xpdf_cv_func_select_arg" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_func_select_arg" >&5
+$as_echo "$xpdf_cv_func_select_arg" >&6; }
if test "$xpdf_cv_func_select_arg" != yes; then
- cat >>confdefs.h <<\_ACEOF
-#define SELECT_TAKES_INT 1
+ $as_echo "#define SELECT_TAKES_INT 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::sort" >&5
+$as_echo_n "checking for std::sort... " >&6; }
+if test "${xpdf_cv_func_std_sort+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <algorithm>
+struct functor {
+ bool operator()(const int &i0, const int &i1) { return i0 < i1; }
+};
+int
+main ()
+{
+int a[100];
+std::sort(a, a+100, functor());
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ xpdf_cv_func_std_sort=yes
+else
+ xpdf_cv_func_std_sort=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xpdf_cv_func_std_sort" >&5
+$as_echo "$xpdf_cv_func_std_sort" >&6; }
+if test "$xpdf_cv_func_std_sort" = yes; then
+ $as_echo "#define HAVE_STD_SORT 1" >>confdefs.h
fi
@@ -6118,29 +5507,25 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-# Check whether --enable-largefile or --disable-largefile was given.
-if test "${enable_largefile+set}" = set; then
- enableval="$enable_largefile"
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+ enableval=$enable_largefile;
+fi
-fi;
if test "$enable_largefile" != no; then
- echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
-echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
-if test "${ac_cv_sys_largefile_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_cv_sys_largefile_CC=no
if test "$GCC" != yes; then
ac_save_CC=$CC
while :; do
- # IRIX 6.2 and later do not support large files by default,
- # so use the C compiler's -n32 option if that helps.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -6159,89 +5544,34 @@ main ()
return 0;
}
_ACEOF
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ if ac_fn_c_try_compile "$LINENO"; then :
break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
fi
-rm -f conftest.err conftest.$ac_objext
- CC="$CC -n32"
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_largefile_CC=' -n32'; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
fi
-rm -f conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext
break
done
CC=$ac_save_CC
rm -f conftest.$ac_ext
fi
fi
-echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
- echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
-echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
-if test "${ac_cv_sys_file_offset_bits+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
while :; do
- ac_cv_sys_file_offset_bits=no
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -6260,40 +5590,11 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=no; break
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
@@ -6313,60 +5614,33 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=64; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
break
done
fi
-echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
-echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
-if test "$ac_cv_sys_file_offset_bits" != no; then
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
cat >>confdefs.h <<_ACEOF
#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
_ACEOF
-
-fi
-rm -f conftest*
- echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
-echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
-if test "${ac_cv_sys_large_files+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
while :; do
- ac_cv_sys_large_files=no
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -6385,40 +5659,11 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=no; break
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include <sys/types.h>
@@ -6438,322 +5683,102 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=1; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
break
done
fi
-echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
-echo "${ECHO_T}$ac_cv_sys_large_files" >&6
-if test "$ac_cv_sys_large_files" != no; then
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
cat >>confdefs.h <<_ACEOF
#define _LARGE_FILES $ac_cv_sys_large_files
_ACEOF
-
-fi
-rm -f conftest*
+;;
+esac
+rm -rf conftest*
+ fi
fi
-echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
-echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6
-if test "${ac_cv_sys_largefile_source+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
while :; do
- ac_cv_sys_largefile_source=no
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdio.h>
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
int
main ()
{
-return !fseeko;
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_sys_largefile_source=no; break
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGEFILE_SOURCE 1
-#include <stdio.h>
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
int
main ()
{
-return !fseeko;
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_sys_largefile_source=1; break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_cv_sys_largefile_source=unknown
break
done
fi
-echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6
-if test "$ac_cv_sys_largefile_source" != no; then
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
+$as_echo "$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+ no | unknown) ;;
+ *)
cat >>confdefs.h <<_ACEOF
#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
_ACEOF
-
-fi
-rm -f conftest*
+;;
+esac
+rm -rf conftest*
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
# in glibc 2.1.3, but that breaks too many other things.
# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
-echo "$as_me:$LINENO: checking for fseeko" >&5
-echo $ECHO_N "checking for fseeko... $ECHO_C" >&6
-if test "${ac_cv_func_fseeko+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdio.h>
-int
-main ()
-{
-return fseeko && fseeko (stdin, 0, 0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_fseeko=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if test $ac_cv_sys_largefile_source != unknown; then
-ac_cv_func_fseeko=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_fseeko" >&5
-echo "${ECHO_T}$ac_cv_func_fseeko" >&6
-if test $ac_cv_func_fseeko = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_FSEEKO 1
-_ACEOF
+$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
fi
-
for ac_func in fseek64
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
+do :
+ ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64"
+if test "x$ac_cv_func_fseek64" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_FSEEK64 1
_ACEOF
xpdf_cv_func_fseek64=yes
else
@@ -6761,103 +5786,12 @@ else
fi
done
-
for ac_func in ftell64
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_var=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
+do :
+ ac_fn_c_check_func "$LINENO" "ftell64" "ac_cv_func_ftell64"
+if test "x$ac_cv_func_ftell64" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_FTELL64 1
_ACEOF
xpdf_cv_func_ftell64=yes
else
@@ -6866,38 +5800,147 @@ fi
done
if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_FSEEK64 1
-_ACEOF
+ $as_echo "#define HAVE_FSEEK64 1" >>confdefs.h
fi
if test -z "$no_x"; then
- echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6
-if test "${ac_cv_prog_egrep+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if echo a | (grep -E '(a|b)') >/dev/null 2>&1
- then ac_cv_prog_egrep='grep -E'
- else ac_cv_prog_egrep='egrep'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
-echo "${ECHO_T}$ac_cv_prog_egrep" >&6
- EGREP=$ac_cv_prog_egrep
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
-echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
-if test "${ac_cv_header_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdarg.h>
@@ -6912,51 +5955,23 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_header_stdc=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_header_stdc=no
+ ac_cv_header_stdc=no
fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
else
ac_cv_header_stdc=no
fi
@@ -6966,18 +5981,14 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
+ $EGREP "free" >/dev/null 2>&1; then :
+
else
ac_cv_header_stdc=no
fi
@@ -6987,16 +5998,13 @@ fi
if test $ac_cv_header_stdc = yes; then
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then
+ if test "$cross_compiling" = yes; then :
:
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ctype.h>
+#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
@@ -7016,109 +6024,40 @@ main ()
for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i))
|| toupper (i) != TOUPPER (i))
- exit(2);
- exit (0);
+ return 2;
+ return 0;
}
_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_run "$LINENO"; then :
-( exit $ac_status )
-ac_cv_header_stdc=no
+else
+ ac_cv_header_stdc=no
fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
+
fi
fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
if test $ac_cv_header_stdc = yes; then
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
fi
# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_Header=no"
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
@@ -7144,21 +6083,21 @@ done
-# Check whether --with-Xpm-library or --without-Xpm-library was given.
-if test "${with_Xpm_library+set}" = set; then
- withval="$with_Xpm_library"
- smr_cv_with_Xpm_library=$withval
-fi;
+# Check whether --with-Xpm-library was given.
+if test "${with_Xpm_library+set}" = set; then :
+ withval=$with_Xpm_library; smr_cv_with_Xpm_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Xpm library" >&5
-echo $ECHO_N "checking whether to use Xpm library... $ECHO_C" >&6
-if test "${smr_cv_with_Xpm_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xpm library" >&5
+$as_echo_n "checking whether to use Xpm library... " >&6; }
+if test "${smr_cv_with_Xpm_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xpm_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xpm_library" >&5
-echo "${ECHO_T}$smr_cv_with_Xpm_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xpm_library" >&5
+$as_echo "$smr_cv_with_Xpm_library" >&6; }
case x"$smr_cv_with_Xpm_library" in
@@ -7176,9 +6115,7 @@ echo "${ECHO_T}$smr_cv_with_Xpm_library" >&6
elif test -d "$smr_cv_with_Xpm_library"; then
Xpm_LIBS="-L$smr_cv_with_Xpm_library -lXpm"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Xpm=yes
;;
@@ -7202,29 +6139,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Xpm-includes or --without-Xpm-includes was given.
-if test "${with_Xpm_includes+set}" = set; then
- withval="$with_Xpm_includes"
- smr_cv_with_Xpm_includes=$withval
-fi;
+# Check whether --with-Xpm-includes was given.
+if test "${with_Xpm_includes+set}" = set; then :
+ withval=$with_Xpm_includes; smr_cv_with_Xpm_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the Xpm header files" >&5
-echo $ECHO_N "checking where to find the Xpm header files... $ECHO_C" >&6
-if test "${smr_cv_with_Xpm_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xpm header files" >&5
+$as_echo_n "checking where to find the Xpm header files... " >&6; }
+if test "${smr_cv_with_Xpm_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xpm_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xpm_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Xpm_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xpm_includes" >&5
+$as_echo "$smr_cv_with_Xpm_includes" >&6; }
if test ! x"$smr_cv_with_Xpm_includes" = x; then
if test -d "$smr_cv_with_Xpm_includes"; then
Xpm_CFLAGS="-I$smr_cv_with_Xpm_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Xpm_CFLAGS=
@@ -7234,150 +6169,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Xpm_CFLAGS $X_CFLAGS"
-
-for ac_header in X11/xpm.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in X11/xpm.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/xpm.h" "ac_cv_header_X11_xpm_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_xpm_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_X11_XPM_H 1
_ACEOF
smr_have_Xpm_header=yes
else
@@ -7403,71 +6200,43 @@ done
# (or no header is needed).
if test $smr_have_Xpm_header != no; then
- echo "$as_me:$LINENO: checking for XpmCreatePixmapFromData in -lXpm" >&5
-echo $ECHO_N "checking for XpmCreatePixmapFromData in -lXpm... $ECHO_C" >&6
-if test "${ac_cv_lib_Xpm_XpmCreatePixmapFromData+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpmCreatePixmapFromData in -lXpm" >&5
+$as_echo_n "checking for XpmCreatePixmapFromData in -lXpm... " >&6; }
+if test "${ac_cv_lib_Xpm_XpmCreatePixmapFromData+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXpm $Xpm_CFLAGS $X_CFLAGS $Xpm_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XpmCreatePixmapFromData ();
int
main ()
{
-XpmCreatePixmapFromData ();
+return XpmCreatePixmapFromData ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xpm_XpmCreatePixmapFromData=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xpm_XpmCreatePixmapFromData=no
+ ac_cv_lib_Xpm_XpmCreatePixmapFromData=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&5
-echo "${ECHO_T}$ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&6
-if test $ac_cv_lib_Xpm_XpmCreatePixmapFromData = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&5
+$as_echo "$ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&6; }
+if test "x$ac_cv_lib_Xpm_XpmCreatePixmapFromData" = x""yes; then :
smr_have_Xpm_library=yes
else
smr_have_Xpm_library=no
@@ -7476,18 +6245,18 @@ fi
fi
if test x"$smr_have_Xpm_library" = xyes; then
- echo "$as_me:$LINENO: result: using Xpm library" >&5
-echo "${ECHO_T}using Xpm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Xpm library" >&5
+$as_echo "using Xpm library" >&6; }
else
Xpm_LIBS=
Xpm_CFLAGS=
if test x"$with_Xpm" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Xpm library" >&5
-echo "${ECHO_T}not using Xpm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Xpm library" >&5
+$as_echo "not using Xpm library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Xpm library not found!" >&5
-echo "$as_me: WARNING: requested Xpm library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Xpm library not found!" >&5
+$as_echo "$as_me: WARNING: requested Xpm library not found!" >&2;}
fi
fi
fi
@@ -7525,21 +6294,21 @@ if test -z "$no_x"; then
-# Check whether --with-Xext-library or --without-Xext-library was given.
-if test "${with_Xext_library+set}" = set; then
- withval="$with_Xext_library"
- smr_cv_with_Xext_library=$withval
-fi;
+# Check whether --with-Xext-library was given.
+if test "${with_Xext_library+set}" = set; then :
+ withval=$with_Xext_library; smr_cv_with_Xext_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Xext library" >&5
-echo $ECHO_N "checking whether to use Xext library... $ECHO_C" >&6
-if test "${smr_cv_with_Xext_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xext library" >&5
+$as_echo_n "checking whether to use Xext library... " >&6; }
+if test "${smr_cv_with_Xext_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xext_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xext_library" >&5
-echo "${ECHO_T}$smr_cv_with_Xext_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xext_library" >&5
+$as_echo "$smr_cv_with_Xext_library" >&6; }
case x"$smr_cv_with_Xext_library" in
@@ -7557,9 +6326,7 @@ echo "${ECHO_T}$smr_cv_with_Xext_library" >&6
elif test -d "$smr_cv_with_Xext_library"; then
Xext_LIBS="-L$smr_cv_with_Xext_library -lXext"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Xext=yes
;;
@@ -7583,29 +6350,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Xext-includes or --without-Xext-includes was given.
-if test "${with_Xext_includes+set}" = set; then
- withval="$with_Xext_includes"
- smr_cv_with_Xext_includes=$withval
-fi;
+# Check whether --with-Xext-includes was given.
+if test "${with_Xext_includes+set}" = set; then :
+ withval=$with_Xext_includes; smr_cv_with_Xext_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the Xext header files" >&5
-echo $ECHO_N "checking where to find the Xext header files... $ECHO_C" >&6
-if test "${smr_cv_with_Xext_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xext header files" >&5
+$as_echo_n "checking where to find the Xext header files... " >&6; }
+if test "${smr_cv_with_Xext_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xext_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xext_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Xext_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xext_includes" >&5
+$as_echo "$smr_cv_with_Xext_includes" >&6; }
if test ! x"$smr_cv_with_Xext_includes" = x; then
if test -d "$smr_cv_with_Xext_includes"; then
Xext_CFLAGS="-I$smr_cv_with_Xext_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Xext_CFLAGS=
@@ -7615,150 +6380,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Xext_CFLAGS $X_CFLAGS"
-
-for ac_header in X11/Xlib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in X11/Xlib.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/Xlib.h" "ac_cv_header_X11_Xlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_Xlib_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_X11_XLIB_H 1
_ACEOF
smr_have_Xext_header=yes
else
@@ -7784,71 +6411,43 @@ done
# (or no header is needed).
if test $smr_have_Xext_header != no; then
- echo "$as_me:$LINENO: checking for XextAddDisplay in -lXext" >&5
-echo $ECHO_N "checking for XextAddDisplay in -lXext... $ECHO_C" >&6
-if test "${ac_cv_lib_Xext_XextAddDisplay+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XextAddDisplay in -lXext" >&5
+$as_echo_n "checking for XextAddDisplay in -lXext... " >&6; }
+if test "${ac_cv_lib_Xext_XextAddDisplay+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXext $Xext_CFLAGS $X_CFLAGS $Xext_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XextAddDisplay ();
int
main ()
{
-XextAddDisplay ();
+return XextAddDisplay ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xext_XextAddDisplay=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xext_XextAddDisplay=no
+ ac_cv_lib_Xext_XextAddDisplay=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XextAddDisplay" >&5
-echo "${ECHO_T}$ac_cv_lib_Xext_XextAddDisplay" >&6
-if test $ac_cv_lib_Xext_XextAddDisplay = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XextAddDisplay" >&5
+$as_echo "$ac_cv_lib_Xext_XextAddDisplay" >&6; }
+if test "x$ac_cv_lib_Xext_XextAddDisplay" = x""yes; then :
smr_have_Xext_library=yes
else
smr_have_Xext_library=no
@@ -7857,18 +6456,18 @@ fi
fi
if test x"$smr_have_Xext_library" = xyes; then
- echo "$as_me:$LINENO: result: using Xext library" >&5
-echo "${ECHO_T}using Xext library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Xext library" >&5
+$as_echo "using Xext library" >&6; }
else
Xext_LIBS=
Xext_CFLAGS=
if test x"$with_Xext" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Xext library" >&5
-echo "${ECHO_T}not using Xext library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Xext library" >&5
+$as_echo "not using Xext library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Xext library not found!" >&5
-echo "$as_me: WARNING: requested Xext library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Xext library not found!" >&5
+$as_echo "$as_me: WARNING: requested Xext library not found!" >&2;}
fi
fi
fi
@@ -7903,21 +6502,21 @@ echo "$as_me: WARNING: requested Xext library not found!" >&2;}
-# Check whether --with-Xp-library or --without-Xp-library was given.
-if test "${with_Xp_library+set}" = set; then
- withval="$with_Xp_library"
- smr_cv_with_Xp_library=$withval
-fi;
+# Check whether --with-Xp-library was given.
+if test "${with_Xp_library+set}" = set; then :
+ withval=$with_Xp_library; smr_cv_with_Xp_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Xp library" >&5
-echo $ECHO_N "checking whether to use Xp library... $ECHO_C" >&6
-if test "${smr_cv_with_Xp_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xp library" >&5
+$as_echo_n "checking whether to use Xp library... " >&6; }
+if test "${smr_cv_with_Xp_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xp_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xp_library" >&5
-echo "${ECHO_T}$smr_cv_with_Xp_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xp_library" >&5
+$as_echo "$smr_cv_with_Xp_library" >&6; }
case x"$smr_cv_with_Xp_library" in
@@ -7935,9 +6534,7 @@ echo "${ECHO_T}$smr_cv_with_Xp_library" >&6
elif test -d "$smr_cv_with_Xp_library"; then
Xp_LIBS="-L$smr_cv_with_Xp_library -lXp"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Xp=yes
;;
@@ -7961,29 +6558,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Xp-includes or --without-Xp-includes was given.
-if test "${with_Xp_includes+set}" = set; then
- withval="$with_Xp_includes"
- smr_cv_with_Xp_includes=$withval
-fi;
+# Check whether --with-Xp-includes was given.
+if test "${with_Xp_includes+set}" = set; then :
+ withval=$with_Xp_includes; smr_cv_with_Xp_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the Xp header files" >&5
-echo $ECHO_N "checking where to find the Xp header files... $ECHO_C" >&6
-if test "${smr_cv_with_Xp_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xp header files" >&5
+$as_echo_n "checking where to find the Xp header files... " >&6; }
+if test "${smr_cv_with_Xp_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xp_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xp_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Xp_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xp_includes" >&5
+$as_echo "$smr_cv_with_Xp_includes" >&6; }
if test ! x"$smr_cv_with_Xp_includes" = x; then
if test -d "$smr_cv_with_Xp_includes"; then
Xp_CFLAGS="-I$smr_cv_with_Xp_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Xp_CFLAGS=
@@ -7993,150 +6588,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Xp_CFLAGS $X_CFLAGS"
-
-for ac_header in X11/extensions/Print.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in X11/extensions/Print.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/extensions/Print.h" "ac_cv_header_X11_extensions_Print_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_extensions_Print_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_X11_EXTENSIONS_PRINT_H 1
_ACEOF
smr_have_Xp_header=yes
else
@@ -8162,71 +6619,43 @@ done
# (or no header is needed).
if test $smr_have_Xp_header != no; then
- echo "$as_me:$LINENO: checking for XpStartPage in -lXp" >&5
-echo $ECHO_N "checking for XpStartPage in -lXp... $ECHO_C" >&6
-if test "${ac_cv_lib_Xp_XpStartPage+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpStartPage in -lXp" >&5
+$as_echo_n "checking for XpStartPage in -lXp... " >&6; }
+if test "${ac_cv_lib_Xp_XpStartPage+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXp $Xp_CFLAGS $X_CFLAGS $Xp_LIBS $X_LIBS $X_PRE_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XpStartPage ();
int
main ()
{
-XpStartPage ();
+return XpStartPage ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xp_XpStartPage=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xp_XpStartPage=no
+ ac_cv_lib_Xp_XpStartPage=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xp_XpStartPage" >&5
-echo "${ECHO_T}$ac_cv_lib_Xp_XpStartPage" >&6
-if test $ac_cv_lib_Xp_XpStartPage = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xp_XpStartPage" >&5
+$as_echo "$ac_cv_lib_Xp_XpStartPage" >&6; }
+if test "x$ac_cv_lib_Xp_XpStartPage" = x""yes; then :
smr_have_Xp_library=yes
else
smr_have_Xp_library=no
@@ -8235,18 +6664,18 @@ fi
fi
if test x"$smr_have_Xp_library" = xyes; then
- echo "$as_me:$LINENO: result: using Xp library" >&5
-echo "${ECHO_T}using Xp library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Xp library" >&5
+$as_echo "using Xp library" >&6; }
else
Xp_LIBS=
Xp_CFLAGS=
if test x"$with_Xp" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Xp library" >&5
-echo "${ECHO_T}not using Xp library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Xp library" >&5
+$as_echo "not using Xp library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Xp library not found!" >&5
-echo "$as_me: WARNING: requested Xp library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Xp library not found!" >&5
+$as_echo "$as_me: WARNING: requested Xp library not found!" >&2;}
fi
fi
fi
@@ -8281,21 +6710,21 @@ echo "$as_me: WARNING: requested Xp library not found!" >&2;}
-# Check whether --with-Xt-library or --without-Xt-library was given.
-if test "${with_Xt_library+set}" = set; then
- withval="$with_Xt_library"
- smr_cv_with_Xt_library=$withval
-fi;
+# Check whether --with-Xt-library was given.
+if test "${with_Xt_library+set}" = set; then :
+ withval=$with_Xt_library; smr_cv_with_Xt_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Xt library" >&5
-echo $ECHO_N "checking whether to use Xt library... $ECHO_C" >&6
-if test "${smr_cv_with_Xt_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xt library" >&5
+$as_echo_n "checking whether to use Xt library... " >&6; }
+if test "${smr_cv_with_Xt_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xt_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xt_library" >&5
-echo "${ECHO_T}$smr_cv_with_Xt_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xt_library" >&5
+$as_echo "$smr_cv_with_Xt_library" >&6; }
case x"$smr_cv_with_Xt_library" in
@@ -8313,9 +6742,7 @@ echo "${ECHO_T}$smr_cv_with_Xt_library" >&6
elif test -d "$smr_cv_with_Xt_library"; then
Xt_LIBS="-L$smr_cv_with_Xt_library -lXt"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Xt=yes
;;
@@ -8339,29 +6766,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Xt-includes or --without-Xt-includes was given.
-if test "${with_Xt_includes+set}" = set; then
- withval="$with_Xt_includes"
- smr_cv_with_Xt_includes=$withval
-fi;
+# Check whether --with-Xt-includes was given.
+if test "${with_Xt_includes+set}" = set; then :
+ withval=$with_Xt_includes; smr_cv_with_Xt_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the Xt header files" >&5
-echo $ECHO_N "checking where to find the Xt header files... $ECHO_C" >&6
-if test "${smr_cv_with_Xt_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xt header files" >&5
+$as_echo_n "checking where to find the Xt header files... " >&6; }
+if test "${smr_cv_with_Xt_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xt_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xt_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Xt_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xt_includes" >&5
+$as_echo "$smr_cv_with_Xt_includes" >&6; }
if test ! x"$smr_cv_with_Xt_includes" = x; then
if test -d "$smr_cv_with_Xt_includes"; then
Xt_CFLAGS="-I$smr_cv_with_Xt_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Xt_CFLAGS=
@@ -8371,150 +6796,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Xt_CFLAGS $X_CFLAGS"
-
-for ac_header in X11/Intrinsic.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in X11/Intrinsic.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/Intrinsic.h" "ac_cv_header_X11_Intrinsic_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_Intrinsic_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_X11_INTRINSIC_H 1
_ACEOF
smr_have_Xt_header=yes
else
@@ -8540,71 +6827,43 @@ done
# (or no header is needed).
if test $smr_have_Xt_header != no; then
- echo "$as_me:$LINENO: checking for XtAppInitialize in -lXt" >&5
-echo $ECHO_N "checking for XtAppInitialize in -lXt... $ECHO_C" >&6
-if test "${ac_cv_lib_Xt_XtAppInitialize+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtAppInitialize in -lXt" >&5
+$as_echo_n "checking for XtAppInitialize in -lXt... " >&6; }
+if test "${ac_cv_lib_Xt_XtAppInitialize+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXt $Xt_CFLAGS $X_CFLAGS $Xt_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XtAppInitialize ();
int
main ()
{
-XtAppInitialize ();
+return XtAppInitialize ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xt_XtAppInitialize=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xt_XtAppInitialize=no
+ ac_cv_lib_Xt_XtAppInitialize=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xt_XtAppInitialize" >&5
-echo "${ECHO_T}$ac_cv_lib_Xt_XtAppInitialize" >&6
-if test $ac_cv_lib_Xt_XtAppInitialize = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtAppInitialize" >&5
+$as_echo "$ac_cv_lib_Xt_XtAppInitialize" >&6; }
+if test "x$ac_cv_lib_Xt_XtAppInitialize" = x""yes; then :
smr_have_Xt_library=yes
else
smr_have_Xt_library=no
@@ -8613,18 +6872,18 @@ fi
fi
if test x"$smr_have_Xt_library" = xyes; then
- echo "$as_me:$LINENO: result: using Xt library" >&5
-echo "${ECHO_T}using Xt library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Xt library" >&5
+$as_echo "using Xt library" >&6; }
else
Xt_LIBS=
Xt_CFLAGS=
if test x"$with_Xt" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Xt library" >&5
-echo "${ECHO_T}not using Xt library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Xt library" >&5
+$as_echo "not using Xt library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Xt library not found!" >&5
-echo "$as_me: WARNING: requested Xt library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Xt library not found!" >&5
+$as_echo "$as_me: WARNING: requested Xt library not found!" >&2;}
fi
fi
fi
@@ -8659,21 +6918,21 @@ echo "$as_me: WARNING: requested Xt library not found!" >&2;}
-# Check whether --with-Xm-library or --without-Xm-library was given.
-if test "${with_Xm_library+set}" = set; then
- withval="$with_Xm_library"
- smr_cv_with_Xm_library=$withval
-fi;
+# Check whether --with-Xm-library was given.
+if test "${with_Xm_library+set}" = set; then :
+ withval=$with_Xm_library; smr_cv_with_Xm_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Xm library" >&5
-echo $ECHO_N "checking whether to use Xm library... $ECHO_C" >&6
-if test "${smr_cv_with_Xm_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xm library" >&5
+$as_echo_n "checking whether to use Xm library... " >&6; }
+if test "${smr_cv_with_Xm_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xm_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xm_library" >&5
-echo "${ECHO_T}$smr_cv_with_Xm_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xm_library" >&5
+$as_echo "$smr_cv_with_Xm_library" >&6; }
case x"$smr_cv_with_Xm_library" in
@@ -8691,9 +6950,7 @@ echo "${ECHO_T}$smr_cv_with_Xm_library" >&6
elif test -d "$smr_cv_with_Xm_library"; then
Xm_LIBS="-L$smr_cv_with_Xm_library -lXm"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Xm=yes
;;
@@ -8717,29 +6974,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Xm-includes or --without-Xm-includes was given.
-if test "${with_Xm_includes+set}" = set; then
- withval="$with_Xm_includes"
- smr_cv_with_Xm_includes=$withval
-fi;
+# Check whether --with-Xm-includes was given.
+if test "${with_Xm_includes+set}" = set; then :
+ withval=$with_Xm_includes; smr_cv_with_Xm_includes=$withval
+fi
- echo "$as_me:$LINENO: checking where to find the Xm header files" >&5
-echo $ECHO_N "checking where to find the Xm header files... $ECHO_C" >&6
-if test "${smr_cv_with_Xm_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xm header files" >&5
+$as_echo_n "checking where to find the Xm header files... " >&6; }
+if test "${smr_cv_with_Xm_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Xm_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Xm_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Xm_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Xm_includes" >&5
+$as_echo "$smr_cv_with_Xm_includes" >&6; }
if test ! x"$smr_cv_with_Xm_includes" = x; then
if test -d "$smr_cv_with_Xm_includes"; then
Xm_CFLAGS="-I$smr_cv_with_Xm_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Xm_CFLAGS=
@@ -8749,150 +7004,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Xm_CFLAGS $X_CFLAGS"
-
-for ac_header in Xm/XmAll.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in Xm/XmAll.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "Xm/XmAll.h" "ac_cv_header_Xm_XmAll_h" "$ac_includes_default"
+if test "x$ac_cv_header_Xm_XmAll_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_XM_XMALL_H 1
_ACEOF
smr_have_Xm_header=yes
else
@@ -8918,71 +7035,43 @@ done
# (or no header is needed).
if test $smr_have_Xm_header != no; then
- echo "$as_me:$LINENO: checking for XmCreateForm in -lXm" >&5
-echo $ECHO_N "checking for XmCreateForm in -lXm... $ECHO_C" >&6
-if test "${ac_cv_lib_Xm_XmCreateForm+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XmCreateForm in -lXm" >&5
+$as_echo_n "checking for XmCreateForm in -lXm... " >&6; }
+if test "${ac_cv_lib_Xm_XmCreateForm+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXm $Xm_CFLAGS $X_CFLAGS $Xm_LIBS $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XmCreateForm ();
int
main ()
{
-XmCreateForm ();
+return XmCreateForm ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xm_XmCreateForm=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xm_XmCreateForm=no
+ ac_cv_lib_Xm_XmCreateForm=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xm_XmCreateForm" >&5
-echo "${ECHO_T}$ac_cv_lib_Xm_XmCreateForm" >&6
-if test $ac_cv_lib_Xm_XmCreateForm = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xm_XmCreateForm" >&5
+$as_echo "$ac_cv_lib_Xm_XmCreateForm" >&6; }
+if test "x$ac_cv_lib_Xm_XmCreateForm" = x""yes; then :
smr_have_Xm_library=yes
else
smr_have_Xm_library=no
@@ -8991,18 +7080,18 @@ fi
fi
if test x"$smr_have_Xm_library" = xyes; then
- echo "$as_me:$LINENO: result: using Xm library" >&5
-echo "${ECHO_T}using Xm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Xm library" >&5
+$as_echo "using Xm library" >&6; }
else
Xm_LIBS=
Xm_CFLAGS=
if test x"$with_Xm" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Xm library" >&5
-echo "${ECHO_T}not using Xm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Xm library" >&5
+$as_echo "not using Xm library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Xm library not found!" >&5
-echo "$as_me: WARNING: requested Xm library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Xm library not found!" >&5
+$as_echo "$as_me: WARNING: requested Xm library not found!" >&2;}
fi
fi
fi
@@ -9037,21 +7126,21 @@ echo "$as_me: WARNING: requested Xm library not found!" >&2;}
-# Check whether --with-Sgm-library or --without-Sgm-library was given.
-if test "${with_Sgm_library+set}" = set; then
- withval="$with_Sgm_library"
- smr_cv_with_Sgm_library=$withval
-fi;
+# Check whether --with-Sgm-library was given.
+if test "${with_Sgm_library+set}" = set; then :
+ withval=$with_Sgm_library; smr_cv_with_Sgm_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use Sgm library" >&5
-echo $ECHO_N "checking whether to use Sgm library... $ECHO_C" >&6
-if test "${smr_cv_with_Sgm_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Sgm library" >&5
+$as_echo_n "checking whether to use Sgm library... " >&6; }
+if test "${smr_cv_with_Sgm_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Sgm_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Sgm_library" >&5
-echo "${ECHO_T}$smr_cv_with_Sgm_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Sgm_library" >&5
+$as_echo "$smr_cv_with_Sgm_library" >&6; }
case x"$smr_cv_with_Sgm_library" in
@@ -9069,9 +7158,7 @@ echo "${ECHO_T}$smr_cv_with_Sgm_library" >&6
elif test -d "$smr_cv_with_Sgm_library"; then
Sgm_LIBS="-L$smr_cv_with_Sgm_library -lSgm"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_Sgm=yes
;;
@@ -9095,29 +7182,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-Sgm-includes or --without-Sgm-includes was given.
-if test "${with_Sgm_includes+set}" = set; then
- withval="$with_Sgm_includes"
- smr_cv_with_Sgm_includes=$withval
-fi;
+# Check whether --with-Sgm-includes was given.
+if test "${with_Sgm_includes+set}" = set; then :
+ withval=$with_Sgm_includes; smr_cv_with_Sgm_includes=$withval
+fi
- echo "$as_me:$LINENO: checking where to find the Sgm header files" >&5
-echo $ECHO_N "checking where to find the Sgm header files... $ECHO_C" >&6
-if test "${smr_cv_with_Sgm_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Sgm header files" >&5
+$as_echo_n "checking where to find the Sgm header files... " >&6; }
+if test "${smr_cv_with_Sgm_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_Sgm_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_Sgm_includes" >&5
-echo "${ECHO_T}$smr_cv_with_Sgm_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_Sgm_includes" >&5
+$as_echo "$smr_cv_with_Sgm_includes" >&6; }
if test ! x"$smr_cv_with_Sgm_includes" = x; then
if test -d "$smr_cv_with_Sgm_includes"; then
Sgm_CFLAGS="-I$smr_cv_with_Sgm_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
Sgm_CFLAGS=
@@ -9127,150 +7212,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $Sgm_CFLAGS $X_CFLAGS"
-
-for ac_header in Sgm/HPanedW.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in Sgm/HPanedW.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "Sgm/HPanedW.h" "ac_cv_header_Sgm_HPanedW_h" "$ac_includes_default"
+if test "x$ac_cv_header_Sgm_HPanedW_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_SGM_HPANEDW_H 1
_ACEOF
smr_have_Sgm_header=yes
else
@@ -9296,71 +7243,43 @@ done
# (or no header is needed).
if test $smr_have_Sgm_header != no; then
- echo "$as_me:$LINENO: checking for SgCreateHorzPanedWindow in -lSgm" >&5
-echo $ECHO_N "checking for SgCreateHorzPanedWindow in -lSgm... $ECHO_C" >&6
-if test "${ac_cv_lib_Sgm_SgCreateHorzPanedWindow+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SgCreateHorzPanedWindow in -lSgm" >&5
+$as_echo_n "checking for SgCreateHorzPanedWindow in -lSgm... " >&6; }
+if test "${ac_cv_lib_Sgm_SgCreateHorzPanedWindow+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lSgm $Sgm_CFLAGS $X_CFLAGS $Sgm_LIBS $Xm_LIBS $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char SgCreateHorzPanedWindow ();
int
main ()
{
-SgCreateHorzPanedWindow ();
+return SgCreateHorzPanedWindow ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Sgm_SgCreateHorzPanedWindow=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Sgm_SgCreateHorzPanedWindow=no
+ ac_cv_lib_Sgm_SgCreateHorzPanedWindow=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&5
-echo "${ECHO_T}$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&6
-if test $ac_cv_lib_Sgm_SgCreateHorzPanedWindow = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&5
+$as_echo "$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&6; }
+if test "x$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" = x""yes; then :
smr_have_Sgm_library=yes
else
smr_have_Sgm_library=no
@@ -9369,18 +7288,18 @@ fi
fi
if test x"$smr_have_Sgm_library" = xyes; then
- echo "$as_me:$LINENO: result: using Sgm library" >&5
-echo "${ECHO_T}using Sgm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Sgm library" >&5
+$as_echo "using Sgm library" >&6; }
else
Sgm_LIBS=
Sgm_CFLAGS=
if test x"$with_Sgm" = xmaybe; then
- echo "$as_me:$LINENO: result: not using Sgm library" >&5
-echo "${ECHO_T}not using Sgm library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using Sgm library" >&5
+$as_echo "not using Sgm library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested Sgm library not found!" >&5
-echo "$as_me: WARNING: requested Sgm library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested Sgm library not found!" >&5
+$as_echo "$as_me: WARNING: requested Sgm library not found!" >&2;}
fi
fi
fi
@@ -9399,80 +7318,59 @@ echo "$as_me: WARNING: requested Sgm library not found!" >&2;}
if test "x$smr_have_Xt_library" = xyes; then
- echo "$as_me:$LINENO: checking for XtAppSetExitFlag in -lXt" >&5
-echo $ECHO_N "checking for XtAppSetExitFlag in -lXt... $ECHO_C" >&6
-if test "${ac_cv_lib_Xt_XtAppSetExitFlag+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtAppSetExitFlag in -lXt" >&5
+$as_echo_n "checking for XtAppSetExitFlag in -lXt... " >&6; }
+if test "${ac_cv_lib_Xt_XtAppSetExitFlag+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lXt $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char XtAppSetExitFlag ();
int
main ()
{
-XtAppSetExitFlag ();
+return XtAppSetExitFlag ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_Xt_XtAppSetExitFlag=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_Xt_XtAppSetExitFlag=no
+ ac_cv_lib_Xt_XtAppSetExitFlag=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_Xt_XtAppSetExitFlag" >&5
-echo "${ECHO_T}$ac_cv_lib_Xt_XtAppSetExitFlag" >&6
-if test $ac_cv_lib_Xt_XtAppSetExitFlag = yes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_XTAPPSETEXITFLAG 1
-_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtAppSetExitFlag" >&5
+$as_echo "$ac_cv_lib_Xt_XtAppSetExitFlag" >&6; }
+if test "x$ac_cv_lib_Xt_XtAppSetExitFlag" = x""yes; then :
+ $as_echo "#define HAVE_XTAPPSETEXITFLAG 1" >>confdefs.h
fi
fi
fi
+#dnl ##### Check for t1lib.
+#smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer],
+# T1_InitLib, t1lib.h,
+# -lm, $X_CFLAGS)
+# t1lib has some potential security holes, and hasn't been updated in
+# years -- if you really want to use it, uncomment the preceding lines,
+# and comment out the next two lines
+t1_LIBS=""
+t1_CFLAGS=""
@@ -9491,400 +7389,24 @@ fi
-# Check whether --with-t1-library or --without-t1-library was given.
-if test "${with_t1_library+set}" = set; then
- withval="$with_t1_library"
- smr_cv_with_t1_library=$withval
-fi;
- echo "$as_me:$LINENO: checking whether to use t1 library" >&5
-echo $ECHO_N "checking whether to use t1 library... $ECHO_C" >&6
-if test "${smr_cv_with_t1_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- smr_cv_with_t1_library=maybe
-fi
-echo "$as_me:$LINENO: result: $smr_cv_with_t1_library" >&5
-echo "${ECHO_T}$smr_cv_with_t1_library" >&6
- case x"$smr_cv_with_t1_library" in
- xyes | xmaybe)
- t1_LIBS="-lt1"
- with_t1=$smr_cv_with_t1_library
- ;;
- xno)
- t1_LIBS=
- with_t1=no
- ;;
- *)
- if test -f "$smr_cv_with_t1_library"; then
- t1_LIBS=$smr_cv_with_t1_library
- elif test -d "$smr_cv_with_t1_library"; then
- t1_LIBS="-L$smr_cv_with_t1_library -lt1"
- else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
- fi
- with_t1=yes
- ;;
- esac
-
-
-
-
-
-
-
- if test ! x"$with_t1" = xno; then
-
- # If we got this far, then the user didn't explicitly ask not to use
- # the library.
-
-
-
-
-
-
-
-
-# Check whether --with-t1-includes or --without-t1-includes was given.
-if test "${with_t1_includes+set}" = set; then
- withval="$with_t1_includes"
- smr_cv_with_t1_includes=$withval
-fi;
-
- echo "$as_me:$LINENO: checking where to find the t1 header files" >&5
-echo $ECHO_N "checking where to find the t1 header files... $ECHO_C" >&6
-if test "${smr_cv_with_t1_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- smr_cv_with_t1_includes=
+# Check whether --with-freetype2-library was given.
+if test "${with_freetype2_library+set}" = set; then :
+ withval=$with_freetype2_library; smr_cv_with_freetype2_library=$withval
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_t1_includes" >&5
-echo "${ECHO_T}$smr_cv_with_t1_includes" >&6
-
- if test ! x"$smr_cv_with_t1_includes" = x; then
- if test -d "$smr_cv_with_t1_includes"; then
- t1_CFLAGS="-I$smr_cv_with_t1_includes"
- else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
- fi
- else
- t1_CFLAGS=
- fi
-
- smr_test_CPPFLAGS="${CPPFLAGS+set}"
- smr_save_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $t1_CFLAGS $X_CFLAGS"
-for ac_header in t1lib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
- smr_have_t1_header=yes
-else
- smr_have_t1_header=no
-fi
-
-done
-
-
- if test x"$smr_test_CPPFLAGS" = xset; then
- CPPFLAGS=$smr_save_CPPFLAGS
- else
- unset CPPFLAGS
- fi
-
-
-
-
-
-
-
- # We need only look for the library if the header has been found
- # (or no header is needed).
- if test $smr_have_t1_header != no; then
-
- echo "$as_me:$LINENO: checking for T1_InitLib in -lt1" >&5
-echo $ECHO_N "checking for T1_InitLib in -lt1... $ECHO_C" >&6
-if test "${ac_cv_lib_t1_T1_InitLib+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lt1 $t1_CFLAGS $X_CFLAGS $t1_LIBS -lm $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char T1_InitLib ();
-int
-main ()
-{
-T1_InitLib ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_t1_T1_InitLib=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_t1_T1_InitLib=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_t1_T1_InitLib" >&5
-echo "${ECHO_T}$ac_cv_lib_t1_T1_InitLib" >&6
-if test $ac_cv_lib_t1_T1_InitLib = yes; then
- smr_have_t1_library=yes
-else
- smr_have_t1_library=no
-fi
-
- fi
-
- if test x"$smr_have_t1_library" = xyes; then
- echo "$as_me:$LINENO: result: using t1 library" >&5
-echo "${ECHO_T}using t1 library" >&6
- else
- t1_LIBS=
- t1_CFLAGS=
-
- if test x"$with_t1" = xmaybe; then
- echo "$as_me:$LINENO: result: not using t1 library" >&5
-echo "${ECHO_T}not using t1 library" >&6
- else
- { echo "$as_me:$LINENO: WARNING: requested t1 library not found!" >&5
-echo "$as_me: WARNING: requested t1 library not found!" >&2;}
- fi
- fi
- fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Check whether --with-freetype2-library or --without-freetype2-library was given.
-if test "${with_freetype2_library+set}" = set; then
- withval="$with_freetype2_library"
- smr_cv_with_freetype2_library=$withval
-fi;
-
- echo "$as_me:$LINENO: checking whether to use freetype2 library" >&5
-echo $ECHO_N "checking whether to use freetype2 library... $ECHO_C" >&6
-if test "${smr_cv_with_freetype2_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use freetype2 library" >&5
+$as_echo_n "checking whether to use freetype2 library... " >&6; }
+if test "${smr_cv_with_freetype2_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_freetype2_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_freetype2_library" >&5
-echo "${ECHO_T}$smr_cv_with_freetype2_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_freetype2_library" >&5
+$as_echo "$smr_cv_with_freetype2_library" >&6; }
case x"$smr_cv_with_freetype2_library" in
@@ -9902,9 +7424,7 @@ echo "${ECHO_T}$smr_cv_with_freetype2_library" >&6
elif test -d "$smr_cv_with_freetype2_library"; then
freetype2_LIBS="-L$smr_cv_with_freetype2_library -lfreetype"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_freetype2=yes
;;
@@ -9928,29 +7448,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-freetype2-includes or --without-freetype2-includes was given.
-if test "${with_freetype2_includes+set}" = set; then
- withval="$with_freetype2_includes"
- smr_cv_with_freetype2_includes=$withval
-fi;
+# Check whether --with-freetype2-includes was given.
+if test "${with_freetype2_includes+set}" = set; then :
+ withval=$with_freetype2_includes; smr_cv_with_freetype2_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the freetype2 header files" >&5
-echo $ECHO_N "checking where to find the freetype2 header files... $ECHO_C" >&6
-if test "${smr_cv_with_freetype2_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the freetype2 header files" >&5
+$as_echo_n "checking where to find the freetype2 header files... " >&6; }
+if test "${smr_cv_with_freetype2_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_freetype2_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_freetype2_includes" >&5
-echo "${ECHO_T}$smr_cv_with_freetype2_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_freetype2_includes" >&5
+$as_echo "$smr_cv_with_freetype2_includes" >&6; }
if test ! x"$smr_cv_with_freetype2_includes" = x; then
if test -d "$smr_cv_with_freetype2_includes"; then
freetype2_CFLAGS="-I$smr_cv_with_freetype2_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
freetype2_CFLAGS=
@@ -9960,150 +7478,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $freetype2_CFLAGS "
-
-for ac_header in ft2build.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in ft2build.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "ft2build.h" "ac_cv_header_ft2build_h" "$ac_includes_default"
+if test "x$ac_cv_header_ft2build_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_FT2BUILD_H 1
_ACEOF
smr_have_freetype2_header=yes
else
@@ -10129,71 +7509,43 @@ done
# (or no header is needed).
if test $smr_have_freetype2_header != no; then
- echo "$as_me:$LINENO: checking for FT_Get_Name_Index in -lfreetype" >&5
-echo $ECHO_N "checking for FT_Get_Name_Index in -lfreetype... $ECHO_C" >&6
-if test "${ac_cv_lib_freetype_FT_Get_Name_Index+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Get_Name_Index in -lfreetype" >&5
+$as_echo_n "checking for FT_Get_Name_Index in -lfreetype... " >&6; }
+if test "${ac_cv_lib_freetype_FT_Get_Name_Index+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lfreetype $freetype2_CFLAGS $freetype2_LIBS -lm $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char FT_Get_Name_Index ();
int
main ()
{
-FT_Get_Name_Index ();
+return FT_Get_Name_Index ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_freetype_FT_Get_Name_Index=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_freetype_FT_Get_Name_Index=no
+ ac_cv_lib_freetype_FT_Get_Name_Index=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_freetype_FT_Get_Name_Index" >&5
-echo "${ECHO_T}$ac_cv_lib_freetype_FT_Get_Name_Index" >&6
-if test $ac_cv_lib_freetype_FT_Get_Name_Index = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_freetype_FT_Get_Name_Index" >&5
+$as_echo "$ac_cv_lib_freetype_FT_Get_Name_Index" >&6; }
+if test "x$ac_cv_lib_freetype_FT_Get_Name_Index" = x""yes; then :
smr_have_freetype2_library=yes
else
smr_have_freetype2_library=no
@@ -10202,18 +7554,18 @@ fi
fi
if test x"$smr_have_freetype2_library" = xyes; then
- echo "$as_me:$LINENO: result: using freetype2 library" >&5
-echo "${ECHO_T}using freetype2 library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using freetype2 library" >&5
+$as_echo "using freetype2 library" >&6; }
else
freetype2_LIBS=
freetype2_CFLAGS=
if test x"$with_freetype2" = xmaybe; then
- echo "$as_me:$LINENO: result: not using freetype2 library" >&5
-echo "${ECHO_T}not using freetype2 library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using freetype2 library" >&5
+$as_echo "not using freetype2 library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested freetype2 library not found!" >&5
-echo "$as_me: WARNING: requested freetype2 library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested freetype2 library not found!" >&5
+$as_echo "$as_me: WARNING: requested freetype2 library not found!" >&2;}
fi
fi
fi
@@ -10231,13 +7583,9 @@ echo "$as_me: WARNING: requested freetype2 library not found!" >&2;}
if test "x$smr_have_freetype2_library" = xyes; then
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_FREETYPE_FREETYPE_H 1
-_ACEOF
+ $as_echo "#define HAVE_FREETYPE_FREETYPE_H 1" >>confdefs.h
- cat >>confdefs.h <<\_ACEOF
-#define HAVE_SPLASH 1
-_ACEOF
+ $as_echo "#define HAVE_SPLASH 1" >>confdefs.h
fi
@@ -10259,21 +7607,21 @@ fi
-# Check whether --with-libpaper-library or --without-libpaper-library was given.
-if test "${with_libpaper_library+set}" = set; then
- withval="$with_libpaper_library"
- smr_cv_with_libpaper_library=$withval
-fi;
+# Check whether --with-libpaper-library was given.
+if test "${with_libpaper_library+set}" = set; then :
+ withval=$with_libpaper_library; smr_cv_with_libpaper_library=$withval
+fi
+
- echo "$as_me:$LINENO: checking whether to use libpaper library" >&5
-echo $ECHO_N "checking whether to use libpaper library... $ECHO_C" >&6
-if test "${smr_cv_with_libpaper_library+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libpaper library" >&5
+$as_echo_n "checking whether to use libpaper library... " >&6; }
+if test "${smr_cv_with_libpaper_library+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_libpaper_library=maybe
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_libpaper_library" >&5
-echo "${ECHO_T}$smr_cv_with_libpaper_library" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_libpaper_library" >&5
+$as_echo "$smr_cv_with_libpaper_library" >&6; }
case x"$smr_cv_with_libpaper_library" in
@@ -10291,9 +7639,7 @@ echo "${ECHO_T}$smr_cv_with_libpaper_library" >&6
elif test -d "$smr_cv_with_libpaper_library"; then
libpaper_LIBS="-L$smr_cv_with_libpaper_library -lpaper"
else
- { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5
-echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5
fi
with_libpaper=yes
;;
@@ -10317,29 +7663,27 @@ echo "$as_me: error: argument must be boolean, file, or directory" >&2;}
-# Check whether --with-libpaper-includes or --without-libpaper-includes was given.
-if test "${with_libpaper_includes+set}" = set; then
- withval="$with_libpaper_includes"
- smr_cv_with_libpaper_includes=$withval
-fi;
+# Check whether --with-libpaper-includes was given.
+if test "${with_libpaper_includes+set}" = set; then :
+ withval=$with_libpaper_includes; smr_cv_with_libpaper_includes=$withval
+fi
+
- echo "$as_me:$LINENO: checking where to find the libpaper header files" >&5
-echo $ECHO_N "checking where to find the libpaper header files... $ECHO_C" >&6
-if test "${smr_cv_with_libpaper_includes+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the libpaper header files" >&5
+$as_echo_n "checking where to find the libpaper header files... " >&6; }
+if test "${smr_cv_with_libpaper_includes+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
smr_cv_with_libpaper_includes=
fi
-echo "$as_me:$LINENO: result: $smr_cv_with_libpaper_includes" >&5
-echo "${ECHO_T}$smr_cv_with_libpaper_includes" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_libpaper_includes" >&5
+$as_echo "$smr_cv_with_libpaper_includes" >&6; }
if test ! x"$smr_cv_with_libpaper_includes" = x; then
if test -d "$smr_cv_with_libpaper_includes"; then
libpaper_CFLAGS="-I$smr_cv_with_libpaper_includes"
else
- { { echo "$as_me:$LINENO: error: argument must be a directory" >&5
-echo "$as_me: error: argument must be a directory" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error "argument must be a directory" "$LINENO" 5
fi
else
libpaper_CFLAGS=
@@ -10349,150 +7693,12 @@ echo "$as_me: error: argument must be a directory" >&2;}
smr_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $libpaper_CFLAGS "
-
-for ac_header in paper.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists. ##
-## ------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ for ac_header in paper.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "paper.h" "ac_cv_header_paper_h" "$ac_includes_default"
+if test "x$ac_cv_header_paper_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_PAPER_H 1
_ACEOF
smr_have_libpaper_header=yes
else
@@ -10518,71 +7724,43 @@ done
# (or no header is needed).
if test $smr_have_libpaper_header != no; then
- echo "$as_me:$LINENO: checking for paperinit in -lpaper" >&5
-echo $ECHO_N "checking for paperinit in -lpaper... $ECHO_C" >&6
-if test "${ac_cv_lib_paper_paperinit+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for paperinit in -lpaper" >&5
+$as_echo_n "checking for paperinit in -lpaper... " >&6; }
+if test "${ac_cv_lib_paper_paperinit+set}" = set; then :
+ $as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpaper $libpaper_CFLAGS $libpaper_LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any gcc2 internal prototype to avoid an error. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
char paperinit ();
int
main ()
{
-paperinit ();
+return paperinit ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_paper_paperinit=yes
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_paper_paperinit=no
+ ac_cv_lib_paper_paperinit=no
fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_paper_paperinit" >&5
-echo "${ECHO_T}$ac_cv_lib_paper_paperinit" >&6
-if test $ac_cv_lib_paper_paperinit = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_paper_paperinit" >&5
+$as_echo "$ac_cv_lib_paper_paperinit" >&6; }
+if test "x$ac_cv_lib_paper_paperinit" = x""yes; then :
smr_have_libpaper_library=yes
else
smr_have_libpaper_library=no
@@ -10591,18 +7769,18 @@ fi
fi
if test x"$smr_have_libpaper_library" = xyes; then
- echo "$as_me:$LINENO: result: using libpaper library" >&5
-echo "${ECHO_T}using libpaper library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libpaper library" >&5
+$as_echo "using libpaper library" >&6; }
else
libpaper_LIBS=
libpaper_CFLAGS=
if test x"$with_libpaper" = xmaybe; then
- echo "$as_me:$LINENO: result: not using libpaper library" >&5
-echo "${ECHO_T}not using libpaper library" >&6
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using libpaper library" >&5
+$as_echo "not using libpaper library" >&6; }
else
- { echo "$as_me:$LINENO: WARNING: requested libpaper library not found!" >&5
-echo "$as_me: WARNING: requested libpaper library not found!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested libpaper library not found!" >&5
+$as_echo "$as_me: WARNING: requested libpaper library not found!" >&2;}
fi
fi
fi
@@ -10630,7 +7808,8 @@ fi
- ac_config_files="$ac_config_files Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile"
+ac_config_files="$ac_config_files Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile"
+
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -10649,39 +7828,59 @@ _ACEOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
+# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-{
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \).
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;;
+ ;; #(
*)
# `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
- esac;
-} |
+ esac |
+ sort
+) |
sed '
+ /^ac_cv_env_/b end
t clear
- : clear
+ :clear
s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
t end
- /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
- if test -w $cache_file; then
- test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
cat confcache >$cache_file
else
- echo "not updating unwritable cache $cache_file"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -10690,32 +7889,18 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[ ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[ ]*$//;
-}'
-fi
-
DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
- ac_i=`echo "$ac_i" |
- sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
- # 2. Add them.
- ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
- ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs
@@ -10724,11 +7909,13 @@ LTLIBOBJS=$ac_ltlibobjs
: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
@@ -10738,81 +7925,252 @@ cat >$CONFIG_STATUS <<_ACEOF
debug=false
ac_cs_recheck=false
ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
fi
-DUALCASE=1; export DUALCASE # for MKS sh
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
fi
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- $as_unset $as_var
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
fi
-done
+ $as_echo "$as_me: error: $1" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
-# Name of the executable.
-as_me=`$as_basename "$0" ||
+as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
-
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
-# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
@@ -10820,148 +8178,123 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
- sed '
- N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
- t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
- ' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
- # Exit status is that of the last command.
- exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
esac
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
else
- as_expr=false
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
else
as_ln_s='cp -p'
fi
-rm -f conf$$ conf$$.exe conf$$.file
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
+ as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
-as_executable_p="test -f"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -10970,31 +8303,20 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling. Logging --version etc. is OK.
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
+# values after options handling.
+ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59. Invocation command line was
+generated by GNU Autoconf 2.65. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -11002,45 +8324,46 @@ generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
_ACEOF
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
- echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
-if test -n "$ac_config_headers"; then
- echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
-if test -n "$ac_config_links"; then
- echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-if test -n "$ac_config_commands"; then
- echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
-cat >>$CONFIG_STATUS <<\_ACEOF
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
-Usage: $0 [OPTIONS] [FILE]...
+Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
- instantiate the configuration header FILE
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
Configuration files:
$config_files
@@ -11048,84 +8371,84 @@ $config_files
Configuration headers:
$config_headers
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
+Report bugs to the package provider."
-cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.59,
- with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+configured by $0, generated by GNU Autoconf 2.65,
+ with options \\"\$ac_cs_config\\"
-Copyright (C) 2003 Free Software Foundation, Inc.
+Copyright (C) 2009 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-INSTALL="$INSTALL"
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value. By we need to know if files were specified by the user.
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=*)
- ac_option=`expr "x$1" : 'x\([^=]*\)='`
- ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
- -*)
+ *)
ac_option=$1
ac_optarg=$2
ac_shift=shift
;;
- *) # This is not an option, so the user has probably given explicit
- # arguments.
- ac_option=$1
- ac_need_defaults=false;;
esac
case $ac_option in
# Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
- --version | --vers* | -V )
- echo "$ac_cs_version"; exit 0 ;;
- --he | --h)
- # Conflict between --help and --header
- { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; };;
- --help | --hel | -h )
- echo "$ac_cs_usage"; exit 0 ;;
- --debug | --d* | -d )
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
- CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
- CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
# This is an error.
- -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; } ;;
+ -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
- *) ac_config_targets="$ac_config_targets $1" ;;
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
esac
shift
@@ -11139,35 +8462,49 @@ if $ac_cs_silent; then
fi
_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
- echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
- exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
fi
_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
+# Handling of arguments.
for ac_config_target in $ac_config_targets
do
- case "$ac_config_target" in
- # Handling of arguments.
- "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "goo/Makefile" ) CONFIG_FILES="$CONFIG_FILES goo/Makefile" ;;
- "fofi/Makefile" ) CONFIG_FILES="$CONFIG_FILES fofi/Makefile" ;;
- "splash/Makefile" ) CONFIG_FILES="$CONFIG_FILES splash/Makefile" ;;
- "xpdf/Makefile" ) CONFIG_FILES="$CONFIG_FILES xpdf/Makefile" ;;
- "aconf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS aconf.h" ;;
- *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
+ case $ac_config_target in
+ "aconf.h") CONFIG_HEADERS="$CONFIG_HEADERS aconf.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "goo/Makefile") CONFIG_FILES="$CONFIG_FILES goo/Makefile" ;;
+ "fofi/Makefile") CONFIG_FILES="$CONFIG_FILES fofi/Makefile" ;;
+ "splash/Makefile") CONFIG_FILES="$CONFIG_FILES splash/Makefile" ;;
+ "xpdf/Makefile") CONFIG_FILES="$CONFIG_FILES xpdf/Makefile" ;;
+
+ *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
done
+
# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used. Set only those that are not.
# We use the long form for the default assignment because of an extremely
@@ -11178,590 +8515,539 @@ if $ac_need_defaults; then
fi
# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
+# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
- trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
}
-
# Create a (secure) tmp directory for tmp files.
{
- tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -n "$tmp" && test -d "$tmp"
} ||
{
- tmp=./confstat$$-$RANDOM
- (umask 077 && mkdir $tmp)
-} ||
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
{
- echo "$me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
-_ACEOF
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
-cat >>$CONFIG_STATUS <<_ACEOF
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+ || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
-#
-# CONFIG_FILES section.
-#
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
- # Protect against being on the right side of a sed subst in config.status.
- sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
- s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@CXX@,$CXX,;t t
-s,@CXXFLAGS@,$CXXFLAGS,;t t
-s,@ac_ct_CXX@,$ac_ct_CXX,;t t
-s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
-s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
-s,@INSTALL_DATA@,$INSTALL_DATA,;t t
-s,@RANLIB@,$RANLIB,;t t
-s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
-s,@EXE@,$EXE,;t t
-s,@LIBPREFIX@,$LIBPREFIX,;t t
-s,@AR@,$AR,;t t
-s,@UP_DIR@,$UP_DIR,;t t
-s,@CPP@,$CPP,;t t
-s,@X_CFLAGS@,$X_CFLAGS,;t t
-s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t
-s,@X_LIBS@,$X_LIBS,;t t
-s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t
-s,@EGREP@,$EGREP,;t t
-s,@Xpm_LIBS@,$Xpm_LIBS,;t t
-s,@Xpm_CFLAGS@,$Xpm_CFLAGS,;t t
-s,@Xext_LIBS@,$Xext_LIBS,;t t
-s,@Xext_CFLAGS@,$Xext_CFLAGS,;t t
-s,@Xp_LIBS@,$Xp_LIBS,;t t
-s,@Xp_CFLAGS@,$Xp_CFLAGS,;t t
-s,@Xt_LIBS@,$Xt_LIBS,;t t
-s,@Xt_CFLAGS@,$Xt_CFLAGS,;t t
-s,@Xm_LIBS@,$Xm_LIBS,;t t
-s,@Xm_CFLAGS@,$Xm_CFLAGS,;t t
-s,@Sgm_LIBS@,$Sgm_LIBS,;t t
-s,@Sgm_CFLAGS@,$Sgm_CFLAGS,;t t
-s,@t1_LIBS@,$t1_LIBS,;t t
-s,@t1_CFLAGS@,$t1_CFLAGS,;t t
-s,@freetype2_LIBS@,$freetype2_LIBS,;t t
-s,@freetype2_CFLAGS@,$freetype2_CFLAGS,;t t
-s,@libpaper_LIBS@,$libpaper_LIBS,;t t
-s,@libpaper_CFLAGS@,$libpaper_CFLAGS,;t t
-s,@X@,$X,;t t
-s,@XPDF_TARGET@,$XPDF_TARGET,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
_ACEOF
- cat >>$CONFIG_STATUS <<\_ACEOF
- # Split the substitutions into bite-sized pieces for seds with
- # small command number limits, like on Digital OSF/1 and HP-UX.
- ac_max_sed_lines=48
- ac_sed_frag=1 # Number of current file.
- ac_beg=1 # First line for current file.
- ac_end=$ac_max_sed_lines # Line after last line for current file.
- ac_more_lines=:
- ac_sed_cmds=
- while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- else
- sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- fi
- if test ! -s $tmp/subs.frag; then
- ac_more_lines=false
- else
- # The purpose of the label and of the branching condition is to
- # speed up the sed processing (if there are no `@' at all, there
- # is no need to browse any of the substitutions).
- # These are the two extra sed commands mentioned above.
- (echo ':t
- /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
- fi
- ac_sed_frag=`expr $ac_sed_frag + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_lines`
- fi
- done
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_t"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
-fi # test -n "$CONFIG_FILES"
+done
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case $ac_file in
- - | *:- | *:-:* ) # input from stdin
- cat >$tmp/stdin
- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- * ) ac_file_in=$ac_file.in ;;
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
esac
- # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
- ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+ ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
ac_builddir=.
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
case $srcdir in
- .) # No --srcdir option. We are building in place.
+ .) # We are building in place.
ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
case $INSTALL in
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
esac
+_ACEOF
- if test x"$ac_file" != x-; then
- { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
- rm -f "$ac_file"
- fi
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- if test x"$ac_file" = x-; then
- configure_input=
- else
- configure_input="$ac_file. "
- fi
- configure_input=$configure_input"Generated from `echo $ac_file_in |
- sed 's,.*/,,'` by configure."
-
- # First look for the input files in the build tree, otherwise in the
- # src tree.
- ac_file_inputs=`IFS=:
- for f in $ac_file_in; do
- case $f in
- -) echo $tmp/stdin ;;
- [\\/$]*)
- # Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- echo "$f";;
- *) # Relative
- if test -f "$f"; then
- # Build tree
- echo "$f"
- elif test -f "$srcdir/$f"; then
- # Source tree
- echo "$srcdir/$f"
- else
- # /dev/null tree
- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- fi;;
- esac
- done` || { (exit 1); exit 1; }
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
- sed "$ac_vpsub
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-s,@INSTALL@,$ac_INSTALL,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
- rm -f $tmp/stdin
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
if test x"$ac_file" != x-; then
- mv $tmp/out $ac_file
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+ } >"$tmp/config.h" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$tmp/config.h" "$ac_file" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ fi
else
- cat $tmp/out
- rm -f $tmp/out
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error "could not create -" "$LINENO" 5
fi
+ ;;
-done
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-#
-# CONFIG_HEADER section.
-#
-
-# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
-# NAME is the cpp macro being defined and VALUE is the value it is being given.
-#
-# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
-ac_dB='[ ].*$,\1#\2'
-ac_dC=' '
-ac_dD=',;t'
-# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
-ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='$,\1#\2define\3'
-ac_uC=' '
-ac_uD=',;t'
-
-for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case $ac_file in
- - | *:- | *:-:* ) # input from stdin
- cat >$tmp/stdin
- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- * ) ac_file_in=$ac_file.in ;;
esac
- test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-
- # First look for the input files in the build tree, otherwise in the
- # src tree.
- ac_file_inputs=`IFS=:
- for f in $ac_file_in; do
- case $f in
- -) echo $tmp/stdin ;;
- [\\/$]*)
- # Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- # Do quote $f, to prevent DOS paths from being IFS'd.
- echo "$f";;
- *) # Relative
- if test -f "$f"; then
- # Build tree
- echo "$f"
- elif test -f "$srcdir/$f"; then
- # Source tree
- echo "$srcdir/$f"
- else
- # /dev/null tree
- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- fi;;
- esac
- done` || { (exit 1); exit 1; }
- # Remove the trailing spaces.
- sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
-
-_ACEOF
-
-# Transform confdefs.h into two sed scripts, `conftest.defines' and
-# `conftest.undefs', that substitutes the proper values into
-# config.h.in to produce config.h. The first handles `#define'
-# templates, and the second `#undef' templates.
-# And first: Protect against being on the right side of a sed subst in
-# config.status. Protect against being in an unquoted here document
-# in config.status.
-rm -f conftest.defines conftest.undefs
-# Using a here document instead of a string reduces the quoting nightmare.
-# Putting comments in sed scripts is not portable.
-#
-# `end' is used to avoid that the second main sed command (meant for
-# 0-ary CPP macros) applies to n-ary macro definitions.
-# See the Autoconf documentation for `clear'.
-cat >confdef2sed.sed <<\_ACEOF
-s/[\\&,]/\\&/g
-s,[\\$`],\\&,g
-t clear
-: clear
-s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
-t end
-s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
-: end
-_ACEOF
-# If some macros were called several times there might be several times
-# the same #defines, which is useless. Nevertheless, we may not want to
-# sort them, since we want the *last* AC-DEFINE to be honored.
-uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
-sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
-rm -f confdef2sed.sed
-
-# This sed command replaces #undef with comments. This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-cat >>conftest.undefs <<\_ACEOF
-s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
-_ACEOF
-
-# Break up conftest.defines because some shells have a limit on the size
-# of here documents, and old seds have small limits too (100 cmds).
-echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
-echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
-echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
-echo ' :' >>$CONFIG_STATUS
-rm -f conftest.tail
-while grep . conftest.defines >/dev/null
-do
- # Write a limited-size here document to $tmp/defines.sed.
- echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
- # Speed up: don't consider the non `#define' lines.
- echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
- # Work around the forget-to-reset-the-flag bug.
- echo 't clr' >>$CONFIG_STATUS
- echo ': clr' >>$CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
- echo 'CEOF
- sed -f $tmp/defines.sed $tmp/in >$tmp/out
- rm -f $tmp/in
- mv $tmp/out $tmp/in
-' >>$CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
- rm -f conftest.defines
- mv conftest.tail conftest.defines
-done
-rm -f conftest.defines
-echo ' fi # grep' >>$CONFIG_STATUS
-echo >>$CONFIG_STATUS
-
-# Break up conftest.undefs because some shells have a limit on the size
-# of here documents, and old seds have small limits too (100 cmds).
-echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
-rm -f conftest.tail
-while grep . conftest.undefs >/dev/null
-do
- # Write a limited-size here document to $tmp/undefs.sed.
- echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
- # Speed up: don't consider the non `#undef'
- echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
- # Work around the forget-to-reset-the-flag bug.
- echo 't clr' >>$CONFIG_STATUS
- echo ': clr' >>$CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
- echo 'CEOF
- sed -f $tmp/undefs.sed $tmp/in >$tmp/out
- rm -f $tmp/in
- mv $tmp/out $tmp/in
-' >>$CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
- rm -f conftest.undefs
- mv conftest.tail conftest.undefs
-done
-rm -f conftest.undefs
-
-cat >>$CONFIG_STATUS <<\_ACEOF
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- if test x"$ac_file" = x-; then
- echo "/* Generated by configure. */" >$tmp/config.h
- else
- echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
- fi
- cat $tmp/in >>$tmp/config.h
- rm -f $tmp/in
- if test x"$ac_file" != x-; then
- if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
- { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
-echo "$as_me: $ac_file is unchanged" >&6;}
- else
- ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
- rm -f $ac_file
- mv $tmp/config.h $ac_file
- fi
- else
- cat $tmp/config.h
- rm -f $tmp/config.h
- fi
-done
-_ACEOF
+done # for ac_tag
-cat >>$CONFIG_STATUS <<\_ACEOF
-{ (exit 0); exit 0; }
+as_fn_exit 0
_ACEOF
-chmod +x $CONFIG_STATUS
ac_clean_files=$ac_clean_files_save
+test $ac_write_fail = 0 ||
+ as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
@@ -11781,25 +9067,31 @@ if test "$no_create" != yes; then
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
- $ac_cs_success || { (exit 1); exit 1; }
+ $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_library" != xyes; then
if test -n "$no_x"; then
- { echo "$as_me:$LINENO: WARNING: Couldn't find X" >&5
-echo "$as_me: WARNING: Couldn't find X" >&2;};
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Couldn't find X" >&5
+$as_echo "$as_me: WARNING: Couldn't find X" >&2;};
fi
if test "x$smr_have_Xm_library" != xyes; then
- { echo "$as_me:$LINENO: WARNING: Couldn't find Motif" >&5
-echo "$as_me: WARNING: Couldn't find Motif" >&2;};
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Couldn't find Motif" >&5
+$as_echo "$as_me: WARNING: Couldn't find Motif" >&2;};
fi
if test "x$smr_have_freetype2_library" != xyes; then
- { echo "$as_me:$LINENO: WARNING: Couldn't find FreeType" >&5
-echo "$as_me: WARNING: Couldn't find FreeType" >&2;};
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Couldn't find FreeType" >&5
+$as_echo "$as_me: WARNING: Couldn't find FreeType" >&2;};
fi
- { echo "$as_me:$LINENO: WARNING: -- You will be able to compile pdftops, pdftotext,
- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&5
-echo "$as_me: WARNING: -- You will be able to compile pdftops, pdftotext,
- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -- You will be able to compile pdftops, pdftotext,
+ pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf
+ or pdftoppm" >&5
+$as_echo "$as_me: WARNING: -- You will be able to compile pdftops, pdftotext,
+ pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf
+ or pdftoppm" >&2;}
fi
diff --git a/configure.in b/configure.in
index 81e7015..6592a46 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ dnl Copyright 1998-2005 Glyph & Cog, LLC
AC_PREREQ(2.57)
-AC_INIT(xpdf/xpdf.cc)
+AC_INIT(xpdf/Gfx.cc)
AC_CONFIG_HEADER(aconf.h)
dnl ##### Optional features.
@@ -237,6 +237,21 @@ if test "$xpdf_cv_func_select_arg" != yes; then
AC_DEFINE(SELECT_TAKES_INT)
fi
+dnl ##### Check for std::sort.
+AC_CACHE_CHECK([for std::sort],
+xpdf_cv_func_std_sort,
+[AC_COMPILE_IFELSE(
+ AC_LANG_PROGRAM([[#include <algorithm>
+struct functor {
+ bool operator()(const int &i0, const int &i1) { return i0 < i1; }
+};]],
+ [[int a[[100]];
+std::sort(a, a+100, functor());]]),
+xpdf_cv_func_std_sort=yes, xpdf_cv_func_std_sort=no)])
+if test "$xpdf_cv_func_std_sort" = yes; then
+ AC_DEFINE(HAVE_STD_SORT)
+fi
+
dnl ##### Back to C for the library tests.
AC_LANG_C
@@ -299,10 +314,15 @@ if test -z "$no_x"; then
fi
fi
-dnl ##### Check for t1lib.
-smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer],
- T1_InitLib, t1lib.h,
- -lm, $X_CFLAGS)
+#dnl ##### Check for t1lib.
+#smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer],
+# T1_InitLib, t1lib.h,
+# -lm, $X_CFLAGS)
+# t1lib has some potential security holes, and hasn't been updated in
+# years -- if you really want to use it, uncomment the preceding lines,
+# and comment out the next two lines
+t1_LIBS=""
+t1_CFLAGS=""
AC_SUBST(t1_LIBS)
AC_SUBST(t1_CFLAGS)
@@ -349,5 +369,6 @@ if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_l
AC_MSG_WARN([Couldn't find FreeType]);
fi
AC_MSG_WARN([-- You will be able to compile pdftops, pdftotext,
- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm])
+ pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf
+ or pdftoppm])
fi
diff --git a/dj_make.bat b/dj_make.bat
index d01b792..13c192d 100644
--- a/dj_make.bat
+++ b/dj_make.bat
@@ -20,10 +20,11 @@ del libGoo.a
cd ..\fofi
%CXX% %CXXFLAGS% -c FoFiBase.cc
%CXX% %CXXFLAGS% -c FoFiEncodings.cc
+%CXX% %CXXFLAGS% -c FoFiIdentifier.cc
%CXX% %CXXFLAGS% -c FoFiTrueType.cc
%CXX% %CXXFLAGS% -c FoFiType1.cc
%CXX% %CXXFLAGS% -c FoFiType1C.cc
-%LIBPROG% -rc libfofi.a FoFiBase.o FoFiEncodings.o FoFiTrueType.o FoFiType1.o FoFiType1C.o
+%LIBPROG% -rc libfofi.a FoFiBase.o FoFiEncodings.o FoFiIdentifier.o FoFiTrueType.o FoFiType1.o FoFiType1C.o
cd ..\xpdf
del *.o
@@ -51,6 +52,7 @@ del *.o
%CXX% %CXXFLAGS% -c Link.cc
%CXX% %CXXFLAGS% -c NameToCharCode.cc
%CXX% %CXXFLAGS% -c Object.cc
+%CXX% %CXXFLAGS% -c OptionalContent.cc
%CXX% %CXXFLAGS% -c Outline.cc
%CXX% %CXXFLAGS% -c OutputDev.cc
%CXX% %CXXFLAGS% -c PDFDoc.cc
@@ -76,6 +78,8 @@ del libxpdf.a
%CXX% %CXXFLAGS% -o pdffonts.exe pdffonts.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdfdetach.exe pdfdetach.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
+
%CXX% %CXXFLAGS% -o pdfimages.exe pdfimages.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
cd ..
diff --git a/doc/pdfdetach.1 b/doc/pdfdetach.1
new file mode 100644
index 0000000..1e2f8aa
--- /dev/null
+++ b/doc/pdfdetach.1
@@ -0,0 +1,105 @@
+.\" Copyright 2011 Glyph & Cog, LLC
+.TH pdfdetach 1 "15 August 2011"
+.SH NAME
+pdfdetach \- Portable Document Format (PDF) document embedded file
+extractor (version 3.03)
+.SH SYNOPSIS
+.B pdfdetach
+[options]
+.RI [ PDF-file ]
+.SH DESCRIPTION
+.B Pdfdetach
+lists or extracts embedded files (attachments) from a Portable
+Document Format (PDF) file.
+.SH CONFIGURATION FILE
+Pdfdetach reads a configuration file at startup. It first tries to
+find the user's private config file, ~/.xpdfrc. If that doesn't
+exist, it looks for a system-wide config file, typically
+/usr/local/etc/xpdfrc (but this location can be changed when pdfinfo
+is built). See the
+.BR xpdfrc (5)
+man page for details.
+.SH OPTIONS
+Some of the following options can be set with configuration file
+commands. These are listed in square brackets with the description of
+the corresponding command line option.
+.TP
+.B \-list
+List all of the embedded files in the PDF file. File names are
+converted to the text encoding specified by the "\-enc" switch.
+.TP
+.BI \-save " number"
+Save the specified embedded file. By default, this uses the file name
+associated with the embedded file (as printed by the "\-list" switch);
+the file name can be changed with the "\-o" switch.
+.TP
+.BI \-saveall
+Save all of the embedded files. This uses the file names associated
+with the embedded files (as printed by the "\-list" switch). By
+default, the files are saved in the current directory; this can be
+changed with the "\-o" switch.
+.TP
+.BI \-o " path"
+Set the file name used when saving an embedded file with the "\-save"
+switch, or the directory used by "\-saveall".
+.TP
+.BI \-enc " encoding-name"
+Sets the encoding to use for text output (embedded file names). The
+.I encoding\-name
+must be defined with the unicodeMap command (see
+.BR xpdfrc (5)).
+This defaults to "Latin1" (which is a built-in encoding).
+.RB "[config file: " textEncoding ]
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.BI \-cfg " config-file"
+Read
+.I config-file
+in place of ~/.xpdfrc or the system-wide config file.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The Xpdf tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdfinfo software and documentation are copyright 1996-2011 Glyph &
+Cog, LLC.
+.SH "SEE ALSO"
+.BR xpdf (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdftoppm (1),
+.BR pdfimages (1),
+.BR xpdfrc (5)
+.br
+.B http://www.foolabs.com/xpdf/
diff --git a/doc/pdfdetach.cat b/doc/pdfdetach.cat
new file mode 100644
index 0000000..526bbba
--- /dev/null
+++ b/doc/pdfdetach.cat
@@ -0,0 +1,92 @@
+pdfdetach(1) pdfdetach(1)
+
+
+
+NAME
+ pdfdetach - Portable Document Format (PDF) document embedded file
+ extractor (version 3.03)
+
+SYNOPSIS
+ pdfdetach [options] [PDF-file]
+
+DESCRIPTION
+ Pdfdetach lists or extracts embedded files (attachments) from a Porta-
+ ble Document Format (PDF) file.
+
+CONFIGURATION FILE
+ Pdfdetach reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfinfo is built). See the
+ xpdfrc(5) man page for details.
+
+OPTIONS
+ Some of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -list List all of the embedded files in the PDF file. File names are
+ converted to the text encoding specified by the "-enc" switch.
+
+ -save number
+ Save the specified embedded file. By default, this uses the
+ file name associated with the embedded file (as printed by the
+ "-list" switch); the file name can be changed with the "-o"
+ switch.
+
+ -saveall
+ Save all of the embedded files. This uses the file names asso-
+ ciated with the embedded files (as printed by the "-list"
+ switch). By default, the files are saved in the current direc-
+ tory; this can be changed with the "-o" switch.
+
+ -o path
+ Set the file name used when saving an embedded file with the
+ "-save" switch, or the directory used by "-saveall".
+
+ -enc encoding-name
+ Sets the encoding to use for text output (embedded file names).
+ The encoding-name must be defined with the unicodeMap command
+ (see xpdfrc(5)). This defaults to "Latin1" (which is a built-in
+ encoding). [config file: textEncoding]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+EXIT CODES
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+AUTHOR
+ The pdfinfo software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
+
+SEE ALSO
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ pdftoppm(1), pdfimages(1), xpdfrc(5)
+ http://www.foolabs.com/xpdf/
+
+
+
+ 15 August 2011 pdfdetach(1)
diff --git a/doc/pdfdetach.hlp b/doc/pdfdetach.hlp
new file mode 100644
index 0000000..f85cd0f
--- /dev/null
+++ b/doc/pdfdetach.hlp
@@ -0,0 +1,101 @@
+! Generated automatically by mantohlp
+1 pdfdetach
+
+ pdfdetach - Portable Document Format (PDF) document embedded file
+
+ pdfdetach [options] [PDF-file]
+
+ Pdfdetach lists or extracts embedded files (attachments) from a Porta-
+ ble Document Format (PDF) file.
+
+ ()
+
+2 ONFIGURATION_FIL
+
+ Pdfdetach reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfinfo is built). See the
+ xpdfrc(5) man page for details.
+
+ ()
+
+2 OPTIONS
+
+ Some of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
+
+ -list List all of the embedded files in the PDF file. File names are
+ converted to the text encoding specified by the "-enc" switch.
+
+ -save number
+ Save the specified embedded file. By default, this uses the
+ file name associated with the embedded file (as printed by the
+ "-list" switch); the file name can be changed with the "-o"
+ switch.
+
+ -saveall
+ Save all of the embedded files. This uses the file names asso-
+ ciated with the embedded files (as printed by the "-list"
+ switch). By default, the files are saved in the current direc-
+ tory; this can be changed with the "-o" switch.
+
+ -o path
+ Set the file name used when saving an embedded file with the
+ "-save" switch, or the directory used by "-saveall".
+
+ -enc encoding-name
+ Sets the encoding to use for text output (embedded file names).
+ The encoding-name must be defined with the unicodeMap command
+ (see xpdfrc(5)). This defaults to "Latin1" (which is a built-in
+ encoding). [config file: textEncoding]
+
+ -opw password
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
+
+ -upw password
+ Specify the user password for the PDF file.
+
+ -cfg config-file
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
+
+ -v Print copyright and version information.
+
+ -h Print usage information. (-help and --help are equivalent.)
+
+ ()
+
+2 XIT_CODE
+
+ The Xpdf tools use the following exit codes:
+
+ 0 No error.
+
+ 1 Error opening a PDF file.
+
+ 2 Error opening an output file.
+
+ 3 Error related to PDF permissions.
+
+ 99 Other error.
+
+ ()
+
+2 AUTHOR
+
+ The pdfinfo software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
+
+ ()
+
+2 SEE_ALSO
+
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ pdftoppm(1), pdfimages(1), xpdfrc(5)
+ http://www.foolabs.com/xpdf/
+
+ ()
+
diff --git a/doc/pdffonts.1 b/doc/pdffonts.1
index 4cb3059..6e132ac 100644
--- a/doc/pdffonts.1
+++ b/doc/pdffonts.1
@@ -1,8 +1,8 @@
-.\" Copyright 1999-2007 Glyph & Cog, LLC
-.TH pdffonts 1 "27 February 2007"
+.\" Copyright 1999-2011 Glyph & Cog, LLC
+.TH pdffonts 1 "15 August 2011"
.SH NAME
pdffonts \- Portable Document Format (PDF) font analyzer (version
-3.02)
+3.03)
.SH SYNOPSIS
.B pdffonts
[options]
@@ -128,13 +128,14 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdffonts software and documentation are copyright 1996-2007 Glyph
+The pdffonts software and documentation are copyright 1996-2011 Glyph
& Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
.BR pdftops (1),
.BR pdftotext (1),
.BR pdfinfo (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1),
.BR xpdfrc (5)
diff --git a/doc/pdffonts.cat b/doc/pdffonts.cat
index fa50dcf..b2d92f3 100644
--- a/doc/pdffonts.cat
+++ b/doc/pdffonts.cat
@@ -1,23 +1,21 @@
-pdffonts(1) pdffonts(1)
+pdffonts(1) pdffonts(1)
NAME
- pdffonts - Portable Document Format (PDF) font analyzer
- (version 3.02)
+ pdffonts - Portable Document Format (PDF) font analyzer (version 3.03)
SYNOPSIS
pdffonts [options] [PDF-file]
DESCRIPTION
- Pdffonts lists the fonts used in a Portable Document For-
- mat (PDF) file along with various information for each
- font.
+ Pdffonts lists the fonts used in a Portable Document Format (PDF) file
+ along with various information for each font.
The following information is listed for each font:
- name the font name, exactly as given in the PDF file
- (potentially including a subset prefix)
+ name the font name, exactly as given in the PDF file (potentially
+ including a subset prefix)
type the font type -- see below for details
@@ -25,14 +23,12 @@ DESCRIPTION
sub "yes" if the font is a subset
- uni "yes" if there is an explicit "ToUnicode" map in
- the PDF file (the absence of a ToUnicode map
- doesn't necessarily mean that the text can't be
- converted to Unicode)
+ uni "yes" if there is an explicit "ToUnicode" map in the PDF file
+ (the absence of a ToUnicode map doesn't necessarily mean that
+ the text can't be converted to Unicode)
object ID
- the font dictionary object ID (number and genera-
- tion)
+ the font dictionary object ID (number and generation)
PDF files can contain the following types of fonts:
@@ -46,22 +42,19 @@ DESCRIPTION
CID Type 0C -- 16-bit PostScript CFF font
CID Type 0C (OT) -- OpenType with CID CFF data
CID TrueType -- 16-bit TrueType font
- CID TrueType (OT) -- OpenType with CID TrueType
- data
+ CID TrueType (OT) -- OpenType with CID TrueType data
CONFIGURATION FILE
- Pdffonts reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdffonts is built). See the xpdfrc(5)
- man page for details.
+ Pdffonts reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdffonts is built). See the
+ xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to analyze.
@@ -70,20 +63,19 @@ OPTIONS
Specifies the last page to analyze.
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -99,14 +91,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdffonts software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdffonts software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1),
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 pdffonts(1)
+ 15 August 2011 pdffonts(1)
diff --git a/doc/pdffonts.hlp b/doc/pdffonts.hlp
index f964dc1..c5a6c13 100644
--- a/doc/pdffonts.hlp
+++ b/doc/pdffonts.hlp
@@ -1,19 +1,17 @@
! Generated automatically by mantohlp
1 pdffonts
- pdffonts - Portable Document Format (PDF) font analyzer
- (version
+ pdffonts - Portable Document Format (PDF) font analyzer (version
pdffonts [options] [PDF-file]
- Pdffonts lists the fonts used in a Portable Document For-
- mat (PDF) file along with various information for each
- font.
+ Pdffonts lists the fonts used in a Portable Document Format (PDF) file
+ along with various information for each font.
The following information is listed for each font:
- name the font name, exactly as given in the PDF file
- (potentially including a subset prefix)
+ name the font name, exactly as given in the PDF file (potentially
+ including a subset prefix)
type the font type -- see below for details
@@ -21,14 +19,12 @@
sub "yes" if the font is a subset
- uni "yes" if there is an explicit "ToUnicode" map in
- the PDF file (the absence of a ToUnicode map
- doesn't necessarily mean that the text can't be
- converted to Unicode)
+ uni "yes" if there is an explicit "ToUnicode" map in the PDF file
+ (the absence of a ToUnicode map doesn't necessarily mean that
+ the text can't be converted to Unicode)
object ID
- the font dictionary object ID (number and genera-
- tion)
+ the font dictionary object ID (number and generation)
PDF files can contain the following types of fonts:
@@ -42,28 +38,25 @@
CID Type 0C -- 16-bit PostScript CFF font
CID Type 0C (OT) -- OpenType with CID CFF data
CID TrueType -- 16-bit TrueType font
- CID TrueType (OT) -- OpenType with CID TrueType
- data
+ CID TrueType (OT) -- OpenType with CID TrueType data
- ()
+ ()
2 ONFIGURATION_FIL
- Pdffonts reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdffonts is built). See the xpdfrc(5)
- man page for details.
+ Pdffonts reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdffonts is built). See the
+ xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to analyze.
@@ -72,22 +65,21 @@
Specifies the last page to analyze.
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 XIT_CODE
@@ -103,20 +95,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdffonts software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdffonts software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1),
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/pdfimages.1 b/doc/pdfimages.1
index 8440147..a68a510 100644
--- a/doc/pdfimages.1
+++ b/doc/pdfimages.1
@@ -1,8 +1,8 @@
-.\" Copyright 1998-2007 Glyph & Cog, LLC
-.TH pdfimages 1 "27 February 2007"
+.\" Copyright 1998-2011 Glyph & Cog, LLC
+.TH pdfimages 1 "15 August 2011"
.SH NAME
pdfimages \- Portable Document Format (PDF) image extractor
-(version 3.02)
+(version 3.03)
.SH SYNOPSIS
.B pdfimages
[options]
@@ -88,7 +88,7 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdfimages software and documentation are copyright 1998-2007 Glyph
+The pdfimages software and documentation are copyright 1998-2011 Glyph
& Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
@@ -96,6 +96,7 @@ The pdfimages software and documentation are copyright 1998-2007 Glyph
.BR pdftotext (1),
.BR pdfinfo (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR xpdfrc (5)
.br
diff --git a/doc/pdfimages.cat b/doc/pdfimages.cat
index b5ae119..ee8810c 100644
--- a/doc/pdfimages.cat
+++ b/doc/pdfimages.cat
@@ -1,42 +1,38 @@
-pdfimages(1) pdfimages(1)
+pdfimages(1) pdfimages(1)
NAME
- pdfimages - Portable Document Format (PDF) image extractor
- (version 3.02)
+ pdfimages - Portable Document Format (PDF) image extractor (version
+ 3.03)
SYNOPSIS
pdfimages [options] PDF-file image-root
DESCRIPTION
- Pdfimages saves images from a Portable Document Format
- (PDF) file as Portable Pixmap (PPM), Portable Bitmap
- (PBM), or JPEG files.
+ Pdfimages saves images from a Portable Document Format (PDF) file as
+ Portable Pixmap (PPM), Portable Bitmap (PBM), or JPEG files.
- Pdfimages reads the PDF file, scans one or more pages,
- PDF-file, and writes one PPM, PBM, or JPEG file for each
- image, image-root-nnn.xxx, where nnn is the image number
- and xxx is the image type (.ppm, .pbm, .jpg).
+ Pdfimages reads the PDF file, scans one or more pages, PDF-file, and
+ writes one PPM, PBM, or JPEG file for each image, image-root-nnn.xxx,
+ where nnn is the image number and xxx is the image type (.ppm, .pbm,
+ .jpg).
- NB: pdfimages extracts the raw image data from the PDF
- file, without performing any additional transforms. Any
- rotation, clipping, color inversion, etc. done by the PDF
- content stream is ignored.
+ NB: pdfimages extracts the raw image data from the PDF file, without
+ performing any additional transforms. Any rotation, clipping, color
+ inversion, etc. done by the PDF content stream is ignored.
CONFIGURATION FILE
- Pdfimages reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdfimages is built). See the
+ Pdfimages reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfimages is built). See the
xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to scan.
@@ -44,26 +40,23 @@ OPTIONS
-l number
Specifies the last page to scan.
- -j Normally, all images are written as PBM (for
- monochrome images) or PPM (for non-monochrome
- images) files. With this option, images in DCT
- format are saved as JPEG files. All non-DCT images
- are saved in PBM/PPM format as usual.
+ -j Normally, all images are written as PBM (for monochrome images)
+ or PPM (for non-monochrome images) files. With this option,
+ images in DCT format are saved as JPEG files. All non-DCT
+ images are saved in PBM/PPM format as usual.
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -79,14 +72,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdfimages software and documentation are copyright
- 1998-2007 Glyph & Cog, LLC.
+ The pdfimages software and documentation are copyright 1998-2011 Glyph
+ & Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf-
- fonts(1), pdftoppm(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 pdfimages(1)
+ 15 August 2011 pdfimages(1)
diff --git a/doc/pdfimages.hlp b/doc/pdfimages.hlp
index 9706099..18fef58 100644
--- a/doc/pdfimages.hlp
+++ b/doc/pdfimages.hlp
@@ -5,39 +5,35 @@
pdfimages [options] PDF-file image-root
- Pdfimages saves images from a Portable Document Format
- (PDF) file as Portable Pixmap (PPM), Portable Bitmap
- (PBM), or JPEG files.
+ Pdfimages saves images from a Portable Document Format (PDF) file as
+ Portable Pixmap (PPM), Portable Bitmap (PBM), or JPEG files.
- Pdfimages reads the PDF file, scans one or more pages,
- PDF-file, and writes one PPM, PBM, or JPEG file for each
- image, image-root-nnn.xxx, where nnn is the image number
- and xxx is the image type (.ppm, .pbm, .jpg).
+ Pdfimages reads the PDF file, scans one or more pages, PDF-file, and
+ writes one PPM, PBM, or JPEG file for each image, image-root-nnn.xxx,
+ where nnn is the image number and xxx is the image type (.ppm, .pbm,
+ .jpg).
- NB: pdfimages extracts the raw image data from the PDF
- file, without performing any additional transforms. Any
- rotation, clipping, color inversion, etc. done by the PDF
- content stream is ignored.
+ NB: pdfimages extracts the raw image data from the PDF file, without
+ performing any additional transforms. Any rotation, clipping, color
+ inversion, etc. done by the PDF content stream is ignored.
- ()
+ ()
2 ONFIGURATION_FIL
- Pdfimages reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdfimages is built). See the
+ Pdfimages reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfimages is built). See the
xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to scan.
@@ -45,28 +41,25 @@
-l number
Specifies the last page to scan.
- -j Normally, all images are written as PBM (for
- monochrome images) or PPM (for non-monochrome
- images) files. With this option, images in DCT
- format are saved as JPEG files. All non-DCT images
- are saved in PBM/PPM format as usual.
+ -j Normally, all images are written as PBM (for monochrome images)
+ or PPM (for non-monochrome images) files. With this option,
+ images in DCT format are saved as JPEG files. All non-DCT
+ images are saved in PBM/PPM format as usual.
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 XIT_CODE
@@ -82,20 +75,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdfimages software and documentation are copyright
- 1998-2007 Glyph & Cog, LLC.
+ The pdfimages software and documentation are copyright 1998-2011 Glyph
+ & Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf-
- fonts(1), pdftoppm(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/pdfinfo.1 b/doc/pdfinfo.1
index ca2a813..b6b0498 100644
--- a/doc/pdfinfo.1
+++ b/doc/pdfinfo.1
@@ -1,8 +1,8 @@
-.\" Copyright 1999-2007 Glyph & Cog, LLC
-.TH pdfinfo 1 "27 February 2007"
+.\" Copyright 1999-2011 Glyph & Cog, LLC
+.TH pdfinfo 1 "15 August 2011"
.SH NAME
pdfinfo \- Portable Document Format (PDF) document information
-extractor (version 3.02)
+extractor (version 3.03)
.SH SYNOPSIS
.B pdfinfo
[options]
@@ -45,6 +45,9 @@ In addition, the following information is printed:
tagged (yes/no)
.RE
.RS
+form (AcroForm / XFA / none)
+.RE
+.RS
page count
.RE
.RS
@@ -82,9 +85,9 @@ the corresponding command line option.
.TP
.BI \-f " number"
Specifies the first page to examine. If multiple pages are requested
-using the "-f" and "-l" options, the size of each requested page (and,
-optionally, the bounding boxes for each requested page) are printed.
-Otherwise, only page one is examined.
+using the "\-f" and "\-l" options, the size of each requested page
+(and, optionally, the bounding boxes for each requested page) are
+printed. Otherwise, only page one is examined.
.TP
.BI \-l " number"
Specifies the last page to examine.
@@ -97,6 +100,9 @@ TrimBox, and ArtBox.
Prints document-level metadata. (This is the "Metadata" stream from
the PDF file's Catalog object.)
.TP
+.B \-rawdates
+Prints the raw (undecoded) date strings, directly from the PDF file.
+.TP
.BI \-enc " encoding-name"
Sets the encoding to use for text output. The
.I encoding\-name
@@ -144,13 +150,14 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdfinfo software and documentation are copyright 1996-2007 Glyph &
+The pdfinfo software and documentation are copyright 1996-2011 Glyph &
Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
.BR pdftops (1),
.BR pdftotext (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1),
.BR xpdfrc (5)
diff --git a/doc/pdfinfo.cat b/doc/pdfinfo.cat
index 4b429ab..7f74ced 100644
--- a/doc/pdfinfo.cat
+++ b/doc/pdfinfo.cat
@@ -1,18 +1,17 @@
-pdfinfo(1) pdfinfo(1)
+pdfinfo(1) pdfinfo(1)
NAME
- pdfinfo - Portable Document Format (PDF) document informa-
- tion extractor (version 3.02)
+ pdfinfo - Portable Document Format (PDF) document information extractor
+ (version 3.03)
SYNOPSIS
pdfinfo [options] [PDF-file]
DESCRIPTION
- Pdfinfo prints the contents of the 'Info' dictionary (plus
- some other useful information) from a Portable Document
- Format (PDF) file.
+ Pdfinfo prints the contents of the 'Info' dictionary (plus some other
+ useful information) from a Portable Document Format (PDF) file.
The 'Info' dictionary contains the following values:
@@ -28,6 +27,7 @@ DESCRIPTION
In addition, the following information is printed:
tagged (yes/no)
+ form (AcroForm / XFA / none)
page count
encrypted flag (yes/no)
print and copy permissions (if encrypted)
@@ -38,59 +38,57 @@ DESCRIPTION
metadata (only if requested)
CONFIGURATION FILE
- Pdfinfo reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdfinfo is built). See the xpdfrc(5)
- man page for details.
+ Pdfinfo reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfinfo is built). See the
+ xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
- Specifies the first page to examine. If multiple
- pages are requested using the "-f" and "-l"
- options, the size of each requested page (and,
- optionally, the bounding boxes for each requested
- page) are printed. Otherwise, only page one is
- examined.
+ Specifies the first page to examine. If multiple pages are
+ requested using the "-f" and "-l" options, the size of each
+ requested page (and, optionally, the bounding boxes for each
+ requested page) are printed. Otherwise, only page one is exam-
+ ined.
-l number
Specifies the last page to examine.
- -box Prints the page box bounding boxes: MediaBox, Crop-
- Box, BleedBox, TrimBox, and ArtBox.
+ -box Prints the page box bounding boxes: MediaBox, CropBox, BleedBox,
+ TrimBox, and ArtBox.
- -meta Prints document-level metadata. (This is the
- "Metadata" stream from the PDF file's Catalog
- object.)
+ -meta Prints document-level metadata. (This is the "Metadata" stream
+ from the PDF file's Catalog object.)
+
+ -rawdates
+ Prints the raw (undecoded) date strings, directly from the PDF
+ file.
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). This defaults to "Latin1"
- (which is a built-in encoding). [config file: tex-
- tEncoding]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -106,14 +104,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdfinfo software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdfinfo software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdffonts(1),
+ xpdf(1), pdftops(1), pdftotext(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 pdfinfo(1)
+ 15 August 2011 pdfinfo(1)
diff --git a/doc/pdfinfo.hlp b/doc/pdfinfo.hlp
index 559a123..f408266 100644
--- a/doc/pdfinfo.hlp
+++ b/doc/pdfinfo.hlp
@@ -1,14 +1,12 @@
! Generated automatically by mantohlp
1 pdfinfo
- pdfinfo - Portable Document Format (PDF) document informa-
- tion
+ pdfinfo - Portable Document Format (PDF) document information
pdfinfo [options] [PDF-file]
- Pdfinfo prints the contents of the 'Info' dictionary (plus
- some other useful information) from a Portable Document
- Format (PDF) file.
+ Pdfinfo prints the contents of the 'Info' dictionary (plus some other
+ useful information) from a Portable Document Format (PDF) file.
The 'Info' dictionary contains the following values:
@@ -24,6 +22,7 @@
In addition, the following information is printed:
tagged (yes/no)
+ form (AcroForm / XFA / none)
page count
encrypted flag (yes/no)
print and copy permissions (if encrypted)
@@ -33,68 +32,66 @@
PDF version
metadata (only if requested)
- ()
+ ()
2 ONFIGURATION_FIL
- Pdfinfo reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdfinfo is built). See the xpdfrc(5)
- man page for details.
+ Pdfinfo reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdfinfo is built). See the
+ xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
- Specifies the first page to examine. If multiple
- pages are requested using the "-f" and "-l"
- options, the size of each requested page (and,
- optionally, the bounding boxes for each requested
- page) are printed. Otherwise, only page one is
- examined.
+ Specifies the first page to examine. If multiple pages are
+ requested using the "-f" and "-l" options, the size of each
+ requested page (and, optionally, the bounding boxes for each
+ requested page) are printed. Otherwise, only page one is exam-
+ ined.
-l number
Specifies the last page to examine.
- -box Prints the page box bounding boxes: MediaBox, Crop-
- Box, BleedBox, TrimBox, and ArtBox.
+ -box Prints the page box bounding boxes: MediaBox, CropBox, BleedBox,
+ TrimBox, and ArtBox.
- -meta Prints document-level metadata. (This is the
- "Metadata" stream from the PDF file's Catalog
- object.)
+ -meta Prints document-level metadata. (This is the "Metadata" stream
+ from the PDF file's Catalog object.)
+
+ -rawdates
+ Prints the raw (undecoded) date strings, directly from the PDF
+ file.
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). This defaults to "Latin1"
- (which is a built-in encoding). [config file: tex-
- tEncoding]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 XIT_CODE
@@ -110,20 +107,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdfinfo software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdfinfo software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdffonts(1),
+ xpdf(1), pdftops(1), pdftotext(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/pdftoppm.1 b/doc/pdftoppm.1
index f159490..59a2f18 100644
--- a/doc/pdftoppm.1
+++ b/doc/pdftoppm.1
@@ -1,8 +1,8 @@
-.\" Copyright 2005-2007 Glyph & Cog, LLC
-.TH pdftoppm 1 "27 February 2007"
+.\" Copyright 2005-2011 Glyph & Cog, LLC
+.TH pdftoppm 1 "15 August 2011"
.SH NAME
pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM)
-converter (version 3.02)
+converter (version 3.03)
.SH SYNOPSIS
.B pdftoppm
[options]
@@ -21,6 +21,10 @@ and writes one PPM file for each page,
where
.I nnnnnn
is the page number.
+If
+.I PPM-root
+is \'-', the image is sent to stdout (this is probably only useful
+when converting a single page).
.SH CONFIGURATION FILE
Pdftoppm reads a configuration file at startup. It first tries to
find the user's private config file, ~/.xpdfrc. If that doesn't
@@ -105,7 +109,7 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdftoppm software and documentation are copyright 1996-2007 Glyph
+The pdftoppm software and documentation are copyright 1996-2011 Glyph
& Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
@@ -113,6 +117,7 @@ The pdftoppm software and documentation are copyright 1996-2007 Glyph
.BR pdftotext (1),
.BR pdfinfo (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdfimages (1),
.BR xpdfrc (5)
.br
diff --git a/doc/pdftoppm.cat b/doc/pdftoppm.cat
index af7d3c9..dd0cc78 100644
--- a/doc/pdftoppm.cat
+++ b/doc/pdftoppm.cat
@@ -1,37 +1,36 @@
-pdftoppm(1) pdftoppm(1)
+pdftoppm(1) pdftoppm(1)
NAME
- pdftoppm - Portable Document Format (PDF) to Portable
- Pixmap (PPM) converter (version 3.02)
+ pdftoppm - Portable Document Format (PDF) to Portable Pixmap (PPM) con-
+ verter (version 3.03)
SYNOPSIS
pdftoppm [options] PDF-file PPM-root
DESCRIPTION
- Pdftoppm converts Portable Document Format (PDF) files to
- color image files in Portable Pixmap (PPM) format,
- grayscale image files in Portable Graymap (PGM) format, or
- monochrome image files in Portable Bitmap (PBM) format.
+ Pdftoppm converts Portable Document Format (PDF) files to color image
+ files in Portable Pixmap (PPM) format, grayscale image files in Porta-
+ ble Graymap (PGM) format, or monochrome image files in Portable Bitmap
+ (PBM) format.
- Pdftoppm reads the PDF file, PDF-file, and writes one PPM
- file for each page, PPM-root-nnnnnn.ppm, where nnnnnn is
- the page number.
+ Pdftoppm reads the PDF file, PDF-file, and writes one PPM file for each
+ page, PPM-root-nnnnnn.ppm, where nnnnnn is the page number. If PPM-
+ root is '-', the image is sent to stdout (this is probably only useful
+ when converting a single page).
CONFIGURATION FILE
- Pdftoppm reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftoppm is built). See the xpdfrc(5)
- man page for details.
+ Pdftoppm reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftoppm is built). See the
+ xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to convert.
@@ -40,46 +39,40 @@ OPTIONS
Specifies the last page to convert.
-r number
- Specifies the resolution, in DPI. The default is
- 150 DPI.
+ Specifies the resolution, in DPI. The default is 150 DPI.
- -mono Generate a monochrome PBM file (instead of a color
- PPM file).
+ -mono Generate a monochrome PBM file (instead of a color PPM file).
- -gray Generate a grayscale PGM file (instead of a color
- PPM file).
+ -gray Generate a grayscale PGM file (instead of a color PPM file).
-t1lib yes | no
- Enable or disable t1lib (a Type 1 font rasterizer).
- This defaults to "yes". [config file: enableT1lib]
+ Enable or disable t1lib (a Type 1 font rasterizer). This
+ defaults to "yes". [config file: enableT1lib]
-freetype yes | no
- Enable or disable FreeType (a TrueType / Type 1
- font rasterizer). This defaults to "yes". [config
- file: enableFreeType]
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
-aa yes | no
- Enable or disable font anti-aliasing. This
- defaults to "yes". [config file: antialias]
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
-aaVector yes | no
- Enable or disable vector anti-aliasing. This
- defaults to "yes". [config file: vectorAntialias]
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -95,14 +88,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdftoppm software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftoppm software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf-
- fonts(1), pdfimages(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 pdftoppm(1)
+ 15 August 2011 pdftoppm(1)
diff --git a/doc/pdftoppm.hlp b/doc/pdftoppm.hlp
index bc83e7c..6c370ed 100644
--- a/doc/pdftoppm.hlp
+++ b/doc/pdftoppm.hlp
@@ -1,39 +1,37 @@
! Generated automatically by mantohlp
1 pdftoppm
- pdftoppm - Portable Document Format (PDF) to Portable
- Pixmap (PPM)
+ pdftoppm - Portable Document Format (PDF) to Portable Pixmap (PPM)
pdftoppm [options] PDF-file PPM-root
- Pdftoppm converts Portable Document Format (PDF) files to
- color image files in Portable Pixmap (PPM) format,
- grayscale image files in Portable Graymap (PGM) format, or
- monochrome image files in Portable Bitmap (PBM) format.
+ Pdftoppm converts Portable Document Format (PDF) files to color image
+ files in Portable Pixmap (PPM) format, grayscale image files in Porta-
+ ble Graymap (PGM) format, or monochrome image files in Portable Bitmap
+ (PBM) format.
- Pdftoppm reads the PDF file, PDF-file, and writes one PPM
- file for each page, PPM-root-nnnnnn.ppm, where nnnnnn is
- the page number.
+ Pdftoppm reads the PDF file, PDF-file, and writes one PPM file for each
+ page, PPM-root-nnnnnn.ppm, where nnnnnn is the page number. If PPM-
+ root is '-', the image is sent to stdout (this is probably only useful
+ when converting a single page).
- ()
+ ()
2 ONFIGURATION_FIL
- Pdftoppm reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftoppm is built). See the xpdfrc(5)
- man page for details.
+ Pdftoppm reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftoppm is built). See the
+ xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to convert.
@@ -42,48 +40,42 @@
Specifies the last page to convert.
-r number
- Specifies the resolution, in DPI. The default is
- 150 DPI.
+ Specifies the resolution, in DPI. The default is 150 DPI.
- -mono Generate a monochrome PBM file (instead of a color
- PPM file).
+ -mono Generate a monochrome PBM file (instead of a color PPM file).
- -gray Generate a grayscale PGM file (instead of a color
- PPM file).
+ -gray Generate a grayscale PGM file (instead of a color PPM file).
-t1lib yes | no
- Enable or disable t1lib (a Type 1 font rasterizer).
- This defaults to "yes". [config file: enableT1lib]
+ Enable or disable t1lib (a Type 1 font rasterizer). This
+ defaults to "yes". [config file: enableT1lib]
-freetype yes | no
- Enable or disable FreeType (a TrueType / Type 1
- font rasterizer). This defaults to "yes". [config
- file: enableFreeType]
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
-aa yes | no
- Enable or disable font anti-aliasing. This
- defaults to "yes". [config file: antialias]
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
-aaVector yes | no
- Enable or disable vector anti-aliasing. This
- defaults to "yes". [config file: vectorAntialias]
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 XIT_CODE
@@ -99,20 +91,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdftoppm software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftoppm software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf-
- fonts(1), pdfimages(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/pdftops.1 b/doc/pdftops.1
index c9ec258..9c68827 100644
--- a/doc/pdftops.1
+++ b/doc/pdftops.1
@@ -1,8 +1,8 @@
-.\" Copyright 1996-2007 Glyph & Cog, LLC
-.TH pdftops 1 "27 February 2007"
+.\" Copyright 1996-2011 Glyph & Cog, LLC
+.TH pdftops 1 "15 August 2011"
.SH NAME
pdftops \- Portable Document Format (PDF) to PostScript converter
-(version 3.02)
+(version 3.03)
.SH SYNOPSIS
.B pdftops
[options]
@@ -25,7 +25,7 @@ to
.I file.ps
(or
.I file.eps
-with the -eps option). If
+with the \-eps option). If
.I PS-file
is \'-', the PostScript is sent to stdout.
.SH CONFIGURATION FILE
@@ -50,8 +50,8 @@ Specifies the last page to print.
Generate Level 1 PostScript. The resulting PostScript files will be
significantly larger (if they contain images), but will print on Level
1 printers. This also converts all images to black and white. No
-more than one of the PostScript level options (-level1, -level1sep,
--level2, -level2sep, -level3, -level3Sep) may be given.
+more than one of the PostScript level options (\-level1, \-level1sep,
+\-level2, \-level2sep, \-level3, \-level3Sep) may be given.
.RB "[config file: " psLevel ]
.TP
.B \-level1sep
@@ -78,20 +78,20 @@ CID font embedding and masked image generation.
.TP
.B \-level3Sep
Generate Level 3 separable PostScript. The separation handling is the
-same as for -level2Sep.
+same as for \-level2Sep.
.RB "[config file: " psLevel ]
.TP
.B \-eps
Generate an Encapsulated PostScript (EPS) file. An EPS file contains
a single image, so if you use this option with a multi-page PDF file,
-you must use -f and -l to specify a single page. No more than one of
-the mode options (-eps, -form) may be given.
+you must use \-f and \-l to specify a single page. No more than one of
+the mode options (\-eps, \-form) may be given.
.TP
.B \-form
Generate a PostScript form which can be imported by software that
understands forms. A form contains a single page, so if you use this
-option with a multi-page PDF file, you must use -f and -l to specify a
-single page. The -level1 option cannot be used with -form.
+option with a multi-page PDF file, you must use \-f and \-l to specify a
+single page. The \-level1 option cannot be used with \-form.
.TP
.B \-opi
Generate OPI comments for all images and forms which have OPI
@@ -221,13 +221,14 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdftops software and documentation are copyright 1996-2007 Glyph &
+The pdftops software and documentation are copyright 1996-2011 Glyph &
Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
.BR pdftotext (1),
.BR pdfinfo (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1),
.BR xpdfrc (5)
diff --git a/doc/pdftops.cat b/doc/pdftops.cat
index b370774..8104b37 100644
--- a/doc/pdftops.cat
+++ b/doc/pdftops.cat
@@ -1,37 +1,34 @@
-pdftops(1) pdftops(1)
+pdftops(1) pdftops(1)
NAME
- pdftops - Portable Document Format (PDF) to PostScript
- converter (version 3.02)
+ pdftops - Portable Document Format (PDF) to PostScript converter (ver-
+ sion 3.03)
SYNOPSIS
pdftops [options] [PDF-file [PS-file]]
DESCRIPTION
- Pdftops converts Portable Document Format (PDF) files to
- PostScript so they can be printed.
+ Pdftops converts Portable Document Format (PDF) files to PostScript so
+ they can be printed.
- Pdftops reads the PDF file, PDF-file, and writes a
- PostScript file, PS-file. If PS-file is not specified,
- pdftops converts file.pdf to file.ps (or file.eps with the
- -eps option). If PS-file is '-', the PostScript is sent
- to stdout.
+ Pdftops reads the PDF file, PDF-file, and writes a PostScript file, PS-
+ file. If PS-file is not specified, pdftops converts file.pdf to
+ file.ps (or file.eps with the -eps option). If PS-file is '-', the
+ PostScript is sent to stdout.
CONFIGURATION FILE
- Pdftops reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftops is built). See the xpdfrc(5)
- man page for details.
+ Pdftops reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftops is built). See the
+ xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to print.
@@ -40,167 +37,143 @@ OPTIONS
Specifies the last page to print.
-level1
- Generate Level 1 PostScript. The resulting
- PostScript files will be significantly larger (if
- they contain images), but will print on Level 1
- printers. This also converts all images to black
- and white. No more than one of the PostScript
- level options (-level1, -level1sep, -level2,
- -level2sep, -level3, -level3Sep) may be given.
- [config file: psLevel]
+ Generate Level 1 PostScript. The resulting PostScript files
+ will be significantly larger (if they contain images), but will
+ print on Level 1 printers. This also converts all images to
+ black and white. No more than one of the PostScript level
+ options (-level1, -level1sep, -level2, -level2sep, -level3,
+ -level3Sep) may be given. [config file: psLevel]
-level1sep
- Generate Level 1 separable PostScript. All colors
- are converted to CMYK. Images are written with
- separate stream data for the four components.
- [config file: psLevel]
+ Generate Level 1 separable PostScript. All colors are converted
+ to CMYK. Images are written with separate stream data for the
+ four components. [config file: psLevel]
-level2
- Generate Level 2 PostScript. Level 2 supports
- color images and image compression. This is the
- default setting. [config file: psLevel]
+ Generate Level 2 PostScript. Level 2 supports color images and
+ image compression. This is the default setting. [config file:
+ psLevel]
-level2sep
- Generate Level 2 separable PostScript. All colors
- are converted to CMYK. The PostScript separation
- convention operators are used to handle custom
- (spot) colors. [config file: psLevel]
+ Generate Level 2 separable PostScript. All colors are converted
+ to CMYK. The PostScript separation convention operators are
+ used to handle custom (spot) colors. [config file: psLevel]
-level3
- Generate Level 3 PostScript. This enables all
- Level 2 features plus CID font embedding and masked
- image generation. [config file: psLevel]
+ Generate Level 3 PostScript. This enables all Level 2 features
+ plus CID font embedding and masked image generation. [config
+ file: psLevel]
-level3Sep
- Generate Level 3 separable PostScript. The separa-
- tion handling is the same as for -level2Sep. [con-
- fig file: psLevel]
-
- -eps Generate an Encapsulated PostScript (EPS) file. An
- EPS file contains a single image, so if you use
- this option with a multi-page PDF file, you must
- use -f and -l to specify a single page. No more
- than one of the mode options (-eps, -form) may be
- given.
-
- -form Generate a PostScript form which can be imported by
- software that understands forms. A form contains a
- single page, so if you use this option with a
- multi-page PDF file, you must use -f and -l to
- specify a single page. The -level1 option cannot
- be used with -form.
-
- -opi Generate OPI comments for all images and forms
- which have OPI information. (This option is only
- available if pdftops was compiled with OPI sup-
- port.) [config file: psOPI]
+ Generate Level 3 separable PostScript. The separation handling
+ is the same as for -level2Sep. [config file: psLevel]
+
+ -eps Generate an Encapsulated PostScript (EPS) file. An EPS file
+ contains a single image, so if you use this option with a multi-
+ page PDF file, you must use -f and -l to specify a single page.
+ No more than one of the mode options (-eps, -form) may be given.
+
+ -form Generate a PostScript form which can be imported by software
+ that understands forms. A form contains a single page, so if
+ you use this option with a multi-page PDF file, you must use -f
+ and -l to specify a single page. The -level1 option cannot be
+ used with -form.
+
+ -opi Generate OPI comments for all images and forms which have OPI
+ information. (This option is only available if pdftops was com-
+ piled with OPI support.) [config file: psOPI]
-noembt1
- By default, any Type 1 fonts which are embedded in
- the PDF file are copied into the PostScript file.
- This option causes pdftops to substitute base fonts
- instead. Embedded fonts make PostScript files
- larger, but may be necessary for readable output.
+ By default, any Type 1 fonts which are embedded in the PDF file
+ are copied into the PostScript file. This option causes pdftops
+ to substitute base fonts instead. Embedded fonts make Post-
+ Script files larger, but may be necessary for readable output.
[config file: psEmbedType1Fonts]
-noembtt
- By default, any TrueType fonts which are embedded
- in the PDF file are copied into the PostScript
- file. This option causes pdftops to substitute
- base fonts instead. Embedded fonts make PostScript
- files larger, but may be necessary for readable
- output. Also, some PostScript interpreters do not
- have TrueType rasterizers. [config file: psEm-
- bedTrueTypeFonts]
+ By default, any TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option causes
+ pdftops to substitute base fonts instead. Embedded fonts make
+ PostScript files larger, but may be necessary for readable out-
+ put. Also, some PostScript interpreters do not have TrueType
+ rasterizers. [config file: psEmbedTrueTypeFonts]
-noembcidps
- By default, any CID PostScript fonts which are
- embedded in the PDF file are copied into the
- PostScript file. This option disables that embed-
- ding. No attempt is made to substitute for non-
- embedded CID PostScript fonts. [config file: psEm-
- bedCIDPostScriptFonts]
+ By default, any CID PostScript fonts which are embedded in the
+ PDF file are copied into the PostScript file. This option dis-
+ ables that embedding. No attempt is made to substitute for non-
+ embedded CID PostScript fonts. [config file: psEmbedCID-
+ PostScriptFonts]
-noembcidtt
- By default, any CID TrueType fonts which are embed-
- ded in the PDF file are copied into the PostScript
- file. This option disables that embedding. No
- attempt is made to substitute for non-embedded CID
- TrueType fonts. [config file: psEmbedCIDTrueType-
- Fonts]
+ By default, any CID TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option disables
+ that embedding. No attempt is made to substitute for non-embed-
+ ded CID TrueType fonts. [config file: psEmbedCIDTrueTypeFonts]
-preload
- Convert PDF forms to PS procedures, and preload
- image data. This uses more memory in the
- PostScript interpreter, but generates significantly
- smaller PS files in situations where, e.g., the
- same image is drawn on every page of a long docu-
- ment.
+ Convert PDF forms to PS procedures, and preload image data.
+ This uses more memory in the PostScript interpreter, but gener-
+ ates significantly smaller PS files in situations where, e.g.,
+ the same image is drawn on every page of a long document.
-paper size
- Set the paper size to one of "letter", "legal",
- "A4", or "A3". This can also be set to "match",
- which will set the paper size to match the size
- specified in the PDF file. [config file: psPaper-
- Size]
+ Set the paper size to one of "letter", "legal", "A4", or "A3".
+ This can also be set to "match", which will set the paper size
+ to match the size specified in the PDF file. [config file:
+ psPaperSize]
-paperw size
- Set the paper width, in points. [config file:
- psPaperSize]
+ Set the paper width, in points. [config file: psPaperSize]
-paperh size
- Set the paper height, in points. [config file:
- psPaperSize]
+ Set the paper height, in points. [config file: psPaperSize]
-nocrop
- By default, output is cropped to the CropBox speci-
- fied in the PDF file. This option disables crop-
- ping. [config file: psCrop]
+ By default, output is cropped to the CropBox specified in the
+ PDF file. This option disables cropping. [config file: psCrop]
-expand
- Expand PDF pages smaller than the paper to fill the
- paper. By default, these pages are not scaled.
- [config file: psExpandSmaller]
+ Expand PDF pages smaller than the paper to fill the paper. By
+ default, these pages are not scaled. [config file: psExpandS-
+ maller]
-noshrink
- Don't scale PDF pages which are larger than the
- paper. By default, pages larger than the paper are
- shrunk to fit. [config file: psShrinkLarger]
+ Don't scale PDF pages which are larger than the paper. By
+ default, pages larger than the paper are shrunk to fit. [config
+ file: psShrinkLarger]
-nocenter
- By default, PDF pages smaller than the paper (after
- any scaling) are centered on the paper. This
- option causes them to be aligned to the lower-left
- corner of the paper instead. [config file: psCen-
- ter]
+ By default, PDF pages smaller than the paper (after any scaling)
+ are centered on the paper. This option causes them to be
+ aligned to the lower-left corner of the paper instead. [config
+ file: psCenter]
-pagecrop
- Treat the CropBox as the PDF page size. By
- default, the MediaBox is used as the page size.
+ Treat the CropBox as the PDF page size. By default, the Media-
+ Box is used as the page size.
-duplex
- Set the Duplex pagedevice entry in the PostScript
- file. This tells duplex-capable printers to enable
- duplexing. [config file: psDuplex]
+ Set the Duplex pagedevice entry in the PostScript file. This
+ tells duplex-capable printers to enable duplexing. [config
+ file: psDuplex]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -216,14 +189,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdftops software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftops software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 pdftops(1)
+ 15 August 2011 pdftops(1)
diff --git a/doc/pdftops.hlp b/doc/pdftops.hlp
index 2cdf8da..b93febd 100644
--- a/doc/pdftops.hlp
+++ b/doc/pdftops.hlp
@@ -1,39 +1,35 @@
! Generated automatically by mantohlp
1 pdftops
- pdftops - Portable Document Format (PDF) to PostScript
- converter
+ pdftops - Portable Document Format (PDF) to PostScript converter
pdftops [options] [PDF-file [PS-file]]
- Pdftops converts Portable Document Format (PDF) files to
- PostScript so they can be printed.
+ Pdftops converts Portable Document Format (PDF) files to PostScript so
+ they can be printed.
- Pdftops reads the PDF file, PDF-file, and writes a
- PostScript file, PS-file. If PS-file is not specified,
- pdftops converts file.pdf to file.ps (or file.eps with the
- -eps option). If PS-file is '-', the PostScript is sent
- to stdout.
+ Pdftops reads the PDF file, PDF-file, and writes a PostScript file, PS-
+ file. If PS-file is not specified, pdftops converts file.pdf to
+ file.ps (or file.eps with the -eps option). If PS-file is '-', the
+ PostScript is sent to stdout.
- ()
+ ()
2 ONFIGURATION_FIL
- Pdftops reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftops is built). See the xpdfrc(5)
- man page for details.
+ Pdftops reads a configuration file at startup. It first tries to find
+ the user's private config file, ~/.xpdfrc. If that doesn't exist, it
+ looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftops is built). See the
+ xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to print.
@@ -42,169 +38,145 @@
Specifies the last page to print.
-level1
- Generate Level 1 PostScript. The resulting
- PostScript files will be significantly larger (if
- they contain images), but will print on Level 1
- printers. This also converts all images to black
- and white. No more than one of the PostScript
- level options (-level1, -level1sep, -level2,
- -level2sep, -level3, -level3Sep) may be given.
- [config file: psLevel]
+ Generate Level 1 PostScript. The resulting PostScript files
+ will be significantly larger (if they contain images), but will
+ print on Level 1 printers. This also converts all images to
+ black and white. No more than one of the PostScript level
+ options (-level1, -level1sep, -level2, -level2sep, -level3,
+ -level3Sep) may be given. [config file: psLevel]
-level1sep
- Generate Level 1 separable PostScript. All colors
- are converted to CMYK. Images are written with
- separate stream data for the four components.
- [config file: psLevel]
+ Generate Level 1 separable PostScript. All colors are converted
+ to CMYK. Images are written with separate stream data for the
+ four components. [config file: psLevel]
-level2
- Generate Level 2 PostScript. Level 2 supports
- color images and image compression. This is the
- default setting. [config file: psLevel]
+ Generate Level 2 PostScript. Level 2 supports color images and
+ image compression. This is the default setting. [config file:
+ psLevel]
-level2sep
- Generate Level 2 separable PostScript. All colors
- are converted to CMYK. The PostScript separation
- convention operators are used to handle custom
- (spot) colors. [config file: psLevel]
+ Generate Level 2 separable PostScript. All colors are converted
+ to CMYK. The PostScript separation convention operators are
+ used to handle custom (spot) colors. [config file: psLevel]
-level3
- Generate Level 3 PostScript. This enables all
- Level 2 features plus CID font embedding and masked
- image generation. [config file: psLevel]
+ Generate Level 3 PostScript. This enables all Level 2 features
+ plus CID font embedding and masked image generation. [config
+ file: psLevel]
-level3Sep
- Generate Level 3 separable PostScript. The separa-
- tion handling is the same as for -level2Sep. [con-
- fig file: psLevel]
-
- -eps Generate an Encapsulated PostScript (EPS) file. An
- EPS file contains a single image, so if you use
- this option with a multi-page PDF file, you must
- use -f and -l to specify a single page. No more
- than one of the mode options (-eps, -form) may be
- given.
-
- -form Generate a PostScript form which can be imported by
- software that understands forms. A form contains a
- single page, so if you use this option with a
- multi-page PDF file, you must use -f and -l to
- specify a single page. The -level1 option cannot
- be used with -form.
-
- -opi Generate OPI comments for all images and forms
- which have OPI information. (This option is only
- available if pdftops was compiled with OPI sup-
- port.) [config file: psOPI]
+ Generate Level 3 separable PostScript. The separation handling
+ is the same as for -level2Sep. [config file: psLevel]
+
+ -eps Generate an Encapsulated PostScript (EPS) file. An EPS file
+ contains a single image, so if you use this option with a multi-
+ page PDF file, you must use -f and -l to specify a single page.
+ No more than one of the mode options (-eps, -form) may be given.
+
+ -form Generate a PostScript form which can be imported by software
+ that understands forms. A form contains a single page, so if
+ you use this option with a multi-page PDF file, you must use -f
+ and -l to specify a single page. The -level1 option cannot be
+ used with -form.
+
+ -opi Generate OPI comments for all images and forms which have OPI
+ information. (This option is only available if pdftops was com-
+ piled with OPI support.) [config file: psOPI]
-noembt1
- By default, any Type 1 fonts which are embedded in
- the PDF file are copied into the PostScript file.
- This option causes pdftops to substitute base fonts
- instead. Embedded fonts make PostScript files
- larger, but may be necessary for readable output.
+ By default, any Type 1 fonts which are embedded in the PDF file
+ are copied into the PostScript file. This option causes pdftops
+ to substitute base fonts instead. Embedded fonts make Post-
+ Script files larger, but may be necessary for readable output.
[config file: psEmbedType1Fonts]
-noembtt
- By default, any TrueType fonts which are embedded
- in the PDF file are copied into the PostScript
- file. This option causes pdftops to substitute
- base fonts instead. Embedded fonts make PostScript
- files larger, but may be necessary for readable
- output. Also, some PostScript interpreters do not
- have TrueType rasterizers. [config file: psEm-
- bedTrueTypeFonts]
+ By default, any TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option causes
+ pdftops to substitute base fonts instead. Embedded fonts make
+ PostScript files larger, but may be necessary for readable out-
+ put. Also, some PostScript interpreters do not have TrueType
+ rasterizers. [config file: psEmbedTrueTypeFonts]
-noembcidps
- By default, any CID PostScript fonts which are
- embedded in the PDF file are copied into the
- PostScript file. This option disables that embed-
- ding. No attempt is made to substitute for non-
- embedded CID PostScript fonts. [config file: psEm-
- bedCIDPostScriptFonts]
+ By default, any CID PostScript fonts which are embedded in the
+ PDF file are copied into the PostScript file. This option dis-
+ ables that embedding. No attempt is made to substitute for non-
+ embedded CID PostScript fonts. [config file: psEmbedCID-
+ PostScriptFonts]
-noembcidtt
- By default, any CID TrueType fonts which are embed-
- ded in the PDF file are copied into the PostScript
- file. This option disables that embedding. No
- attempt is made to substitute for non-embedded CID
- TrueType fonts. [config file: psEmbedCIDTrueType-
- Fonts]
+ By default, any CID TrueType fonts which are embedded in the PDF
+ file are copied into the PostScript file. This option disables
+ that embedding. No attempt is made to substitute for non-embed-
+ ded CID TrueType fonts. [config file: psEmbedCIDTrueTypeFonts]
-preload
- Convert PDF forms to PS procedures, and preload
- image data. This uses more memory in the
- PostScript interpreter, but generates significantly
- smaller PS files in situations where, e.g., the
- same image is drawn on every page of a long docu-
- ment.
+ Convert PDF forms to PS procedures, and preload image data.
+ This uses more memory in the PostScript interpreter, but gener-
+ ates significantly smaller PS files in situations where, e.g.,
+ the same image is drawn on every page of a long document.
-paper size
- Set the paper size to one of "letter", "legal",
- "A4", or "A3". This can also be set to "match",
- which will set the paper size to match the size
- specified in the PDF file. [config file: psPaper-
- Size]
+ Set the paper size to one of "letter", "legal", "A4", or "A3".
+ This can also be set to "match", which will set the paper size
+ to match the size specified in the PDF file. [config file:
+ psPaperSize]
-paperw size
- Set the paper width, in points. [config file:
- psPaperSize]
+ Set the paper width, in points. [config file: psPaperSize]
-paperh size
- Set the paper height, in points. [config file:
- psPaperSize]
+ Set the paper height, in points. [config file: psPaperSize]
-nocrop
- By default, output is cropped to the CropBox speci-
- fied in the PDF file. This option disables
- cropping. [config file: psCrop]
+ By default, output is cropped to the CropBox specified in the
+ PDF file. This option disables cropping. [config file: psCrop]
-expand
- Expand PDF pages smaller than the paper to fill the
- paper. By default, these pages are not scaled.
- [config file: psExpandSmaller]
+ Expand PDF pages smaller than the paper to fill the paper. By
+ default, these pages are not scaled. [config file: psExpandS-
+ maller]
-noshrink
- Don't scale PDF pages which are larger than the
- paper. By default, pages larger than the paper are
- shrunk to fit. [config file: psShrinkLarger]
+ Don't scale PDF pages which are larger than the paper. By
+ default, pages larger than the paper are shrunk to fit. [config
+ file: psShrinkLarger]
-nocenter
- By default, PDF pages smaller than the paper (after
- any scaling) are centered on the paper. This
- option causes them to be aligned to the lower-left
- corner of the paper instead. [config file: psCen-
- ter]
+ By default, PDF pages smaller than the paper (after any scaling)
+ are centered on the paper. This option causes them to be
+ aligned to the lower-left corner of the paper instead. [config
+ file: psCenter]
-pagecrop
- Treat the CropBox as the PDF page size. By
- default, the MediaBox is used as the page size.
+ Treat the CropBox as the PDF page size. By default, the Media-
+ Box is used as the page size.
-duplex
- Set the Duplex pagedevice entry in the PostScript
- file. This tells duplex-capable printers to enable
- duplexing. [config file: psDuplex]
+ Set the Duplex pagedevice entry in the PostScript file. This
+ tells duplex-capable printers to enable duplexing. [config
+ file: psDuplex]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 XIT_CODE
@@ -220,20 +192,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdftops software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftops software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/pdftotext.1 b/doc/pdftotext.1
index c16a1ea..83bf7c6 100644
--- a/doc/pdftotext.1
+++ b/doc/pdftotext.1
@@ -1,8 +1,8 @@
-.\" Copyright 1997-2007 Glyph & Cog, LLC
-.TH pdftotext 1 "27 Febuary 2007"
+.\" Copyright 1997-2011 Glyph & Cog, LLC
+.TH pdftotext 1 "15 August 2011"
.SH NAME
pdftotext \- Portable Document Format (PDF) to text converter
-(version 3.02)
+(version 3.03)
.SH SYNOPSIS
.B pdftotext
[options]
@@ -49,6 +49,10 @@ Maintain (as best as possible) the original physical layout of the
text. The default is to \'undo' physical layout (columns,
hyphenation, etc.) and output the text in reading order.
.TP
+.BI \-fixed " number"
+Assume fixed-pitch (or tabular) text, with the specified character
+width (in points). This forces physical layout mode.
+.TP
.B \-raw
Keep the text in content stream order. This is a hack which often
"undoes" column formatting, etc. Use of raw mode is no longer
@@ -123,13 +127,14 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The pdftotext software and documentation are copyright 1996-2007 Glyph
+The pdftotext software and documentation are copyright 1996-2011 Glyph
& Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
.BR pdftops (1),
.BR pdfinfo (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1),
.BR xpdfrc (5)
diff --git a/doc/pdftotext.cat b/doc/pdftotext.cat
index 9990226..5c8a709 100644
--- a/doc/pdftotext.cat
+++ b/doc/pdftotext.cat
@@ -1,36 +1,32 @@
-pdftotext(1) pdftotext(1)
+pdftotext(1) pdftotext(1)
NAME
- pdftotext - Portable Document Format (PDF) to text con-
- verter (version 3.02)
+ pdftotext - Portable Document Format (PDF) to text converter (version
+ 3.03)
SYNOPSIS
pdftotext [options] [PDF-file [text-file]]
DESCRIPTION
- Pdftotext converts Portable Document Format (PDF) files to
- plain text.
+ Pdftotext converts Portable Document Format (PDF) files to plain text.
- Pdftotext reads the PDF file, PDF-file, and writes a text
- file, text-file. If text-file is not specified, pdftotext
- converts file.pdf to file.txt. If text-file is '-', the
- text is sent to stdout.
+ Pdftotext reads the PDF file, PDF-file, and writes a text file, text-
+ file. If text-file is not specified, pdftotext converts file.pdf to
+ file.txt. If text-file is '-', the text is sent to stdout.
CONFIGURATION FILE
- Pdftotext reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftotext is built). See the
+ Pdftotext reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftotext is built). See the
xpdfrc(5) man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to convert.
@@ -39,59 +35,58 @@ OPTIONS
Specifies the last page to convert.
-layout
- Maintain (as best as possible) the original physi-
- cal layout of the text. The default is to 'undo'
- physical layout (columns, hyphenation, etc.) and
- output the text in reading order.
+ Maintain (as best as possible) the original physical layout of
+ the text. The default is to 'undo' physical layout (columns,
+ hyphenation, etc.) and output the text in reading order.
- -raw Keep the text in content stream order. This is a
- hack which often "undoes" column formatting, etc.
- Use of raw mode is no longer recommended.
+ -fixed number
+ Assume fixed-pitch (or tabular) text, with the specified charac-
+ ter width (in points). This forces physical layout mode.
+
+ -raw Keep the text in content stream order. This is a hack which
+ often "undoes" column formatting, etc. Use of raw mode is no
+ longer recommended.
-htmlmeta
- Generate a simple HTML file, including the meta
- information. This simply wraps the text in <pre>
- and </pre> and prepends the meta headers.
+ Generate a simple HTML file, including the meta information.
+ This simply wraps the text in <pre> and </pre> and prepends the
+ meta headers.
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). The encoding name is
- case-sensitive. This defaults to "Latin1" (which
- is a built-in encoding). [config file: textEncod-
- ing]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ The encoding name is case-sensitive. This defaults to "Latin1"
+ (which is a built-in encoding). [config file: textEncoding]
-eol unix | dos | mac
- Sets the end-of-line convention to use for text
- output. [config file: textEOL]
+ Sets the end-of-line convention to use for text output. [config
+ file: textEOL]
-nopgbrk
- Don't insert page breaks (form feed characters)
- between pages. [config file: textPageBreaks]
+ Don't insert page breaks (form feed characters) between pages.
+ [config file: textPageBreaks]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
BUGS
- Some PDF files contain fonts whose encodings have been
- mangled beyond recognition. There is no way (short of
- OCR) to extract text from these files.
+ Some PDF files contain fonts whose encodings have been mangled beyond
+ recognition. There is no way (short of OCR) to extract text from these
+ files.
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -107,14 +102,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The pdftotext software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftotext software and documentation are copyright 1996-2011 Glyph
+ & Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdftoppm(1),
- pdfimages(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
+ pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 Febuary 2007 pdftotext(1)
+ 15 August 2011 pdftotext(1)
diff --git a/doc/pdftotext.hlp b/doc/pdftotext.hlp
index f527172..651af91 100644
--- a/doc/pdftotext.hlp
+++ b/doc/pdftotext.hlp
@@ -1,38 +1,33 @@
! Generated automatically by mantohlp
1 pdftotext
- pdftotext - Portable Document Format (PDF) to text con-
- verter
+ pdftotext - Portable Document Format (PDF) to text converter
pdftotext [options] [PDF-file [text-file]]
- Pdftotext converts Portable Document Format (PDF) files to
- plain text.
+ Pdftotext converts Portable Document Format (PDF) files to plain text.
- Pdftotext reads the PDF file, PDF-file, and writes a text
- file, text-file. If text-file is not specified, pdftotext
- converts file.pdf to file.txt. If text-file is '-', the
- text is sent to stdout.
+ Pdftotext reads the PDF file, PDF-file, and writes a text file, text-
+ file. If text-file is not specified, pdftotext converts file.pdf to
+ file.txt. If text-file is '-', the text is sent to stdout.
- ()
+ ()
2 ONFIGURATION_FIL
- Pdftotext reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when pdftotext is built). See the
+ Pdftotext reads a configuration file at startup. It first tries to
+ find the user's private config file, ~/.xpdfrc. If that doesn't exist,
+ it looks for a system-wide config file, typically /usr/local/etc/xpdfrc
+ (but this location can be changed when pdftotext is built). See the
xpdfrc(5) man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands. These are listed in square brackets
- with the description of the corresponding command line
- option.
+ Many of the following options can be set with configuration file com-
+ mands. These are listed in square brackets with the description of the
+ corresponding command line option.
-f number
Specifies the first page to convert.
@@ -41,64 +36,63 @@
Specifies the last page to convert.
-layout
- Maintain (as best as possible) the original physi-
- cal layout of the text. The default is to 'undo'
- physical layout (columns, hyphenation, etc.) and
- output the text in reading order.
+ Maintain (as best as possible) the original physical layout of
+ the text. The default is to 'undo' physical layout (columns,
+ hyphenation, etc.) and output the text in reading order.
- -raw Keep the text in content stream order. This is a
- hack which often "undoes" column formatting, etc.
- Use of raw mode is no longer recommended.
+ -fixed number
+ Assume fixed-pitch (or tabular) text, with the specified charac-
+ ter width (in points). This forces physical layout mode.
+
+ -raw Keep the text in content stream order. This is a hack which
+ often "undoes" column formatting, etc. Use of raw mode is no
+ longer recommended.
-htmlmeta
- Generate a simple HTML file, including the meta
- information. This simply wraps the text in <pre>
- and </pre> and prepends the meta headers.
+ Generate a simple HTML file, including the meta information.
+ This simply wraps the text in <pre> and </pre> and prepends the
+ meta headers.
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). The encoding name is
- case-sensitive. This defaults to "Latin1" (which
- is a built-in encoding). [config file: textEncod-
- ing]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ The encoding name is case-sensitive. This defaults to "Latin1"
+ (which is a built-in encoding). [config file: textEncoding]
-eol unix | dos | mac
- Sets the end-of-line convention to use for text
- output. [config file: textEOL]
+ Sets the end-of-line convention to use for text output. [config
+ file: textEOL]
-nopgbrk
- Don't insert page breaks (form feed characters)
- between pages. [config file: textPageBreaks]
+ Don't insert page breaks (form feed characters) between pages.
+ [config file: textPageBreaks]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- ()
+ ()
2 BUGS
- Some PDF files contain fonts whose encodings have been
- mangled beyond recognition. There is no way (short of
- OCR) to extract text from these files.
+ Some PDF files contain fonts whose encodings have been mangled beyond
+ recognition. There is no way (short of OCR) to extract text from these
+ files.
- ()
+ ()
2 XIT_CODE
@@ -114,20 +108,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The pdftotext software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The pdftotext software and documentation are copyright 1996-2011 Glyph
+ & Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdftoppm(1),
- pdfimages(1), xpdfrc(5)
+ xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
+ pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/sample-xpdfrc b/doc/sample-xpdfrc
index 481e417..0df70a7 100644
--- a/doc/sample-xpdfrc
+++ b/doc/sample-xpdfrc
@@ -29,26 +29,26 @@
# installed in a "standard" location, xpdf will find them
# automatically.)
-#displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
-#displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
-#displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
-#displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
-#displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
-#displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
-#displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
-#displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
-#displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
-#displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
-#displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
-#displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
-#displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
-#displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+#fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+#fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+#fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+#fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+#fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+#fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+#fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+#fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+#fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+#fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+#fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+#fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+#fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+#fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
# If you need to display PDF files that refer to non-embedded fonts,
# you should add one or more fontDir options to point to the
# directories containing the font files. Xpdf will only look at .pfa,
-# .pfb, and .ttf files in those directories (other files will simply
-# be ignored).
+# .pfb, .ttf, and .ttc files in those directories (other files will
+# simply be ignored).
#fontDir /usr/local/fonts/bakoma
@@ -88,4 +88,5 @@
# Set the command used to run a web browser when a URL hyperlink is
# clicked.
+#launchCommand viewer-script
#urlCommand "netscape -remote 'openURL(%s)'"
diff --git a/doc/xpdf.1 b/doc/xpdf.1
index 6548557..05c0af9 100644
--- a/doc/xpdf.1
+++ b/doc/xpdf.1
@@ -1,7 +1,7 @@
-.\" Copyright 1996-2007 Glyph & Cog, LLC
-.TH xpdf 1 "27 February 2007"
+.\" Copyright 1996-2011 Glyph & Cog, LLC
+.TH xpdf 1 "15 August 2011"
.SH NAME
-xpdf \- Portable Document Format (PDF) file viewer for X (version 3.02)
+xpdf \- Portable Document Format (PDF) file viewer for X (version 3.03)
.SH SYNOPSIS
.B xpdf
[options]
@@ -92,7 +92,7 @@ xpdf.fullScreenMatteColor, for full-screen mode.)
.TP
.BI \-z " zoom"
Set the initial zoom factor. A number specifies a zoom percentage,
-where 100 means 72 dpi.You may also specify \'page', to fit the page
+where 100 means 72 dpi. You may also specify \'page', to fit the page
to the window size, or \'width', to fit the page width to the window
width.
.RB "[config file: " initialZoom "; or X resource: " xpdf.initialZoom ]
@@ -176,16 +176,16 @@ section below).
.BI \-exec " command"
Execute a command (see the
.B COMMANDS
-section below) in an xpdf remote server window (with -remote only).
+section below) in an xpdf remote server window (with \-remote only).
.TP
.B \-reload
-Reload xpdf remote server window (with -remote only).
+Reload xpdf remote server window (with \-remote only).
.TP
.B \-raise
-Raise xpdf remote server window (with -remote only).
+Raise xpdf remote server window (with \-remote only).
.TP
.B \-quit
-Kill xpdf remote server (with -remote only).
+Kill xpdf remote server (with \-remote only).
.TP
.B \-cmd
Print commands as they're executed (useful for debugging).
@@ -259,7 +259,7 @@ Move to a specific page number. Click in the box to activate it, type
the page number, then hit return.
.TP
.B "zoom popup menu"
-Change the zoom factor (see the description of the -z option above).
+Change the zoom factor (see the description of the \-z option above).
.TP
.B "binoculars button"
Find a text string.
@@ -451,7 +451,7 @@ add the lines:
# Use xpdf to view PDF files.
.RE
.RS
-application/pdf; xpdf -q %s
+application/pdf; xpdf \-q %s
.RE
.PP
Make sure that xpdf is on your executable search path.
@@ -462,7 +462,7 @@ occurrence of \'%s' with the URL. For example, to call netscape with
the URL, add this line to your config file:
.PP
.RS
-urlCommand "netscape -remote 'openURL(%s)'"
+urlCommand "netscape \-remote 'openURL(%s)'"
.RE
.SH COMMANDS
Xpdf's key and mouse bindings are user-configurable, using the bind and
@@ -581,6 +581,15 @@ Zoom in - go to the next higher zoom factor.
.B zoomOut
Zoom out - go the next lower zoom factor.
.TP
+.B rotateCW
+Rotate the page 90 degrees clockwise.
+.TP
+.B rotateCCW
+Rotate the page 90 degrees counterclockwise.
+.TP
+.BI setSelection( pg , ulx , uly , lrx , lry )
+Set the selection to the specified coordinates on the specified page.
+.TP
.B continuousMode
Go to continuous view mode.
.TP
@@ -643,6 +652,8 @@ command string:
file is open)
%u => link URL (or an empty string if not over
a URL link)
+ %p => current page number (or an empty string if
+ no file is open)
%x => selection upper-left x coordinate
(or 0 if there is no selection)
%y => selection upper-left y coordinate
@@ -651,6 +662,9 @@ command string:
(or 0 if there is no selection)
%Y => selection lower-right y coordinate
(or 0 if there is no selection)
+ %i => page containing the mouse pointer
+ %j => x coordinate of the mouse pointer
+ %k => y coordinate of the mouse pointer
%% => %
.fi
@@ -806,14 +820,14 @@ Xpdf can be started in remote server mode by specifying a server name
(in addition to the file name and page number). For example:
.PP
.RS
-xpdf -remote myServer file.pdf
+xpdf \-remote myServer file.pdf
.RE
.PP
If there is currently no xpdf running in server mode with the name
\'myServer', a new xpdf window will be opened. If another command:
.PP
.RS
-xpdf -remote myServer another.pdf 9
+xpdf \-remote myServer another.pdf 9
.RE
.PP
is issued, a new copy of xpdf will not be started. Instead, the first
@@ -822,15 +836,15 @@ xpdf (the server) will load
and display page nine. If the file name is the same:
.PP
.RS
-xpdf -remote myServer another.pdf 4
+xpdf \-remote myServer another.pdf 4
.RE
.PP
the xpdf server will simply display the specified page.
.PP
-The -raise option tells the server to raise its window; it can be
+The \-raise option tells the server to raise its window; it can be
specified with or without a file name and page number.
.PP
-The -quit option tells the server to close its window and exit.
+The \-quit option tells the server to close its window and exit.
.SH EXIT CODES
The Xpdf tools use the following exit codes:
.TP
@@ -849,13 +863,14 @@ Error related to PDF permissions.
99
Other error.
.SH AUTHOR
-The xpdf software and documentation are copyright 1996-2007 Glyph &
+The xpdf software and documentation are copyright 1996-2011 Glyph &
Cog, LLC.
.SH "SEE ALSO"
.BR pdftops (1),
.BR pdftotext (1),
.BR pdfinfo (1),
.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1),
.BR xpdfrc (5)
diff --git a/doc/xpdf.cat b/doc/xpdf.cat
index 8ab7291..eab46ab 100644
--- a/doc/xpdf.cat
+++ b/doc/xpdf.cat
@@ -1,233 +1,206 @@
-xpdf(1) xpdf(1)
+xpdf(1) xpdf(1)
NAME
- xpdf - Portable Document Format (PDF) file viewer for X
- (version 3.02)
+ xpdf - Portable Document Format (PDF) file viewer for X (version 3.03)
SYNOPSIS
xpdf [options] [PDF-file [page | +dest]]
DESCRIPTION
- Xpdf is a viewer for Portable Document Format (PDF) files.
- (These are also sometimes also called 'Acrobat' files,
- from the name of Adobe's PDF software.) Xpdf runs under
- the X Window System on UNIX, VMS, and OS/2.
+ Xpdf is a viewer for Portable Document Format (PDF) files. (These are
+ also sometimes also called 'Acrobat' files, from the name of Adobe's
+ PDF software.) Xpdf runs under the X Window System on UNIX, VMS, and
+ OS/2.
To run xpdf, simply type:
xpdf file.pdf
- where file.pdf is your PDF file. The file name can be
- followed by a number specifying the page which should be
- displayed first, e.g.:
+ where file.pdf is your PDF file. The file name can be followed by a
+ number specifying the page which should be displayed first, e.g.:
xpdf file.pdf 18
- You can also give a named destination, prefixed with '+'
- in place of the page number. (This is only useful with
- PDF files that provide named destination targets.)
+ You can also give a named destination, prefixed with '+' in place of
+ the page number. (This is only useful with PDF files that provide
+ named destination targets.)
You can also start xpdf without opening any files:
xpdf
CONFIGURATION FILE
- Xpdf reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when xpdf is built). See the xpdfrc(5) man
- page for details.
+ Xpdf reads a configuration file at startup. It first tries to find the
+ user's private config file, ~/.xpdfrc. If that doesn't exist, it looks
+ for a system-wide config file, typically /usr/local/etc/xpdfrc (but
+ this location can be changed when xpdf is built). See the xpdfrc(5)
+ man page for details.
OPTIONS
- Many of the following options can be set with configura-
- tion file commands or X resources. These are listed in
- square brackets with the description of the corresponding
- command line option.
+ Many of the following options can be set with configuration file com-
+ mands or X resources. These are listed in square brackets with the
+ description of the corresponding command line option.
-g geometry
- Set the initial window geometry. (-geometry is
- equivalent.) [X resource: xpdf.geometry]
+ Set the initial window geometry. (-geometry is equivalent.) [X
+ resource: xpdf.geometry]
-title title
- Set the window title. By default, the title will
- be "xpdf: foo.pdf". [X resource: xpdf.title]
+ Set the window title. By default, the title will be "xpdf:
+ foo.pdf". [X resource: xpdf.title]
- -cmap Install a private colormap. This is ignored on
- TrueColor visuals. [X resource: xpdf.installCmap]
+ -cmap Install a private colormap. This is ignored on TrueColor visu-
+ als. [X resource: xpdf.installCmap]
-rgb number
- Set the size of largest RGB cube xpdf will try to
- allocate. The default is 5 (for a 5x5x5 cube); set
- to a smaller number to conserve color table
- entries. This is ignored with private colormaps
- and on TrueColor visuals. [X resource:
- xpdf.rgbCubeSize]
-
- -rv Set reverse video mode. This reverses the colors
- of everything except images. It may not always
- produce great results for PDF files which do weird
- things with color. This also causes the paper
- color to default to black. [X resource:
- xpdf.reverseVideo]
+ Set the size of largest RGB cube xpdf will try to allocate. The
+ default is 5 (for a 5x5x5 cube); set to a smaller number to con-
+ serve color table entries. This is ignored with private col-
+ ormaps and on TrueColor visuals. [X resource: xpdf.rgbCubeSize]
+
+ -rv Set reverse video mode. This reverses the colors of everything
+ except images. It may not always produce great results for PDF
+ files which do weird things with color. This also causes the
+ paper color to default to black. [X resource: xpdf.reverseV-
+ ideo]
-papercolor color
- Set the "paper color", i.e., the background of the
- page display. This will not work too well with PDF
- files that do things like filling in white behind
- the text. [X resource: xpdf.paperColor]
+ Set the "paper color", i.e., the background of the page display.
+ This will not work too well with PDF files that do things like
+ filling in white behind the text. [X resource: xpdf.paperColor]
-mattecolor color
- Set the matte color, i.e., the color used for back-
- ground outside the actual page area. (There is a
- separate setting, xpdf.fullScreenMatteColor, for
- full-screen mode.) [X resource: xpdf.matteColor]
+ Set the matte color, i.e., the color used for background outside
+ the actual page area. (There is a separate setting,
+ xpdf.fullScreenMatteColor, for full-screen mode.) [X resource:
+ xpdf.matteColor]
-z zoom
- Set the initial zoom factor. A number specifies a
- zoom percentage, where 100 means 72 dpi.You may
- also specify 'page', to fit the page to the window
- size, or 'width', to fit the page width to the win-
- dow width. [config file: initialZoom; or X
+ Set the initial zoom factor. A number specifies a zoom percent-
+ age, where 100 means 72 dpi. You may also specify 'page', to
+ fit the page to the window size, or 'width', to fit the page
+ width to the window width. [config file: initialZoom; or X
resource: xpdf.initialZoom]
- -cont Start in continuous view mode, i.e., with one ver-
- tical scroll bar for the whole document. [config
- file: continuousView]
+ -cont Start in continuous view mode, i.e., with one vertical scroll
+ bar for the whole document. [config file: continuousView]
-t1lib yes | no
- Enable or disable t1lib (a Type 1 font rasterizer).
- This defaults to "yes". [config file: enableT1lib]
+ Enable or disable t1lib (a Type 1 font rasterizer). This
+ defaults to "yes". [config file: enableT1lib]
-freetype yes | no
- Enable or disable FreeType (a TrueType / Type 1
- font rasterizer). This defaults to "yes". [config
- file: enableFreeType]
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
-aa yes | no
- Enable or disable font anti-aliasing. This
- defaults to "yes". [config file: antialias]
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
-aaVector yes | no
- Enable or disable vector anti-aliasing. This
- defaults to "yes". [config file: vectorAntialias]
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
-ps PS-file
- Set the default file name for PostScript output
- (i.e., the name which will appear in the print dia-
- log). This can also be of the form '|command' to
- pipe the PostScript through a command. [config
- file: psFile]
+ Set the default file name for PostScript output (i.e., the name
+ which will appear in the print dialog). This can also be of the
+ form '|command' to pipe the PostScript through a command. [con-
+ fig file: psFile]
-paper size
- Set the paper size to one of "letter", "legal",
- "A4", or "A3". This can also be set to "match",
- which will set the paper size to match the size
- specified in the PDF file. [config file: psPaper-
- Size]
+ Set the paper size to one of "letter", "legal", "A4", or "A3".
+ This can also be set to "match", which will set the paper size
+ to match the size specified in the PDF file. [config file:
+ psPaperSize]
-paperw size
- Set the paper width, in points. [config file:
- psPaperSize]
+ Set the paper width, in points. [config file: psPaperSize]
-paperh size
- Set the paper height, in points. [config file:
- psPaperSize]
+ Set the paper height, in points. [config file: psPaperSize]
-level1
- Generate Level 1 PostScript. The resulting
- PostScript files will be significantly larger (if
- they contain images), but will print on Level 1
- printers. This also converts all images to black
- and white. [config file: psLevel]
+ Generate Level 1 PostScript. The resulting PostScript files
+ will be significantly larger (if they contain images), but will
+ print on Level 1 printers. This also converts all images to
+ black and white. [config file: psLevel]
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). This defaults to "Latin1"
- (which is a built-in encoding). [config file: tex-
- tEncoding]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
-eol unix | dos | mac
- Sets the end-of-line convention to use for text
- output. [config file: textEOL]
+ Sets the end-of-line convention to use for text output. [config
+ file: textEOL]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-fullscreen
- Open xpdf in full-screen mode, useful for presenta-
- tions.
+ Open xpdf in full-screen mode, useful for presentations.
-remote name
- Start/contact xpdf remote server with specified
- name (see the REMOTE SERVER MODE section below).
+ Start/contact xpdf remote server with specified name (see the
+ REMOTE SERVER MODE section below).
-exec command
- Execute a command (see the COMMANDS section below)
- in an xpdf remote server window (with -remote
- only).
+ Execute a command (see the COMMANDS section below) in an xpdf
+ remote server window (with -remote only).
-reload
- Reload xpdf remote server window (with -remote
- only).
+ Reload xpdf remote server window (with -remote only).
- -raise Raise xpdf remote server window (with -remote
- only).
+ -raise Raise xpdf remote server window (with -remote only).
-quit Kill xpdf remote server (with -remote only).
- -cmd Print commands as they're executed (useful for
- debugging). [config file: printCommands]
+ -cmd Print commands as they're executed (useful for debugging).
+ [config file: printCommands]
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- Several other standard X options and resources will work
- as expected:
+ Several other standard X options and resources will work as expected:
-display display
[X resource: xpdf.display]
-fg color
- (-foreground is equivalent.) [X resource:
- xpdf*Foreground]
+ (-foreground is equivalent.) [X resource: xpdf*Foreground]
-bg color
- (-background is equivalent.) [X resource:
- xpdf*Background]
+ (-background is equivalent.) [X resource: xpdf*Background]
-font font
(-fn is equivalent.) [X resource: xpdf*fontList]
- The color and font options only affect the user interface
- elements, not the PDF display (the 'paper').
+ The color and font options only affect the user interface elements, not
+ the PDF display (the 'paper').
- The following X resources do not have command line option
- equivalents:
+ The following X resources do not have command line option equivalents:
xpdf.toolTipEnable
- Enables (if set to true) or disables (if set to
- false) the tool-tips on the toolbar buttons.
+ Enables (if set to true) or disables (if set to false) the tool-
+ tips on the toolbar buttons.
xpdf.fullScreenMatteColor
- Sets the matte color to be used in full-screen
- mode. The default setting is "black".
+ Sets the matte color to be used in full-screen mode. The
+ default setting is "black".
CONTROLS
On-screen controls, at the bottom of the xpdf window
@@ -241,111 +214,103 @@ CONTROLS
Move backward or forward along the history path.
'Page' entry box
- Move to a specific page number. Click in the box
- to activate it, type the page number, then hit
- return.
+ Move to a specific page number. Click in the box to activate
+ it, type the page number, then hit return.
zoom popup menu
- Change the zoom factor (see the description of the
- -z option above).
+ Change the zoom factor (see the description of the -z option
+ above).
binoculars button
Find a text string.
print button
- Bring up a dialog for generating a PostScript file.
- The dialog has options to set the pages to be
- printed and the PostScript file name. The file
- name can be '-' for stdout or '|command' to pipe
- the PostScript through a command, e.g., '|lpr'.
+ Bring up a dialog for generating a PostScript file. The dialog
+ has options to set the pages to be printed and the PostScript
+ file name. The file name can be '-' for stdout or '|command' to
+ pipe the PostScript through a command, e.g., '|lpr'.
'?' button
Bring up the 'about xpdf' window.
link info
- The space between the '?' and 'Quit' buttons is
- used to show the URL or external file name when the
- mouse is over a link.
+ The space between the '?' and 'Quit' buttons is used to show the
+ URL or external file name when the mouse is over a link.
'Quit' button
Quit xpdf.
Menu
- Pressing the right mouse button will post a popup menu
- with the following commands:
+ Pressing the right mouse button will post a popup menu with the follow-
+ ing commands:
Open...
Open a new PDF file via a file requester.
Open in new window...
- Create a new window and open a new PDF file via a
- file requester.
+ Create a new window and open a new PDF file via a file
+ requester.
- Reload Reload the current PDF file. Note that Xpdf will
- reload the file automatically (on a page change or
- redraw) if it has changed since it was last loaded.
+ Reload Reload the current PDF file. Note that Xpdf will reload the
+ file automatically (on a page change or redraw) if it has
+ changed since it was last loaded.
Save as...
Save the current file via a file requester.
Continuous view
- Toggles between single page and continuous view
- modes.
+ Toggles between single page and continuous view modes.
Rotate counterclockwise
Rotate the page 90 degrees counterclockwise.
Rotate clockwise
- Rotate the page 90 degrees clockwise. The two
- rotate commands are intended primarily for PDF
- files where the rotation isn't correctly specified
- in the file.
+ Rotate the page 90 degrees clockwise. The two rotate commands
+ are intended primarily for PDF files where the rotation isn't
+ correctly specified in the file.
Zoom to selection
Zoom in to the currently selected rectangle.
- Close Close the current window. If this is the only open
- window, the document is closed, but the window is
- left open (i.e., this menu command won't quit
- xpdf).
+ Close Close the current window. If this is the only open window, the
+ document is closed, but the window is left open (i.e., this menu
+ command won't quit xpdf).
Quit Quit xpdf.
Outline
- If the PDF contains an outline (a.k.a., bookmarks), there
- will be an outline pane on the left side of the window.
- The width of the outline pane is adjustable with a verti-
- cal split bar via the knob near its bottom end.
+ If the PDF contains an outline (a.k.a., bookmarks), there will be an
+ outline pane on the left side of the window. The width of the outline
+ pane is adjustable with a vertical split bar via the knob near its bot-
+ tom end.
Text selection
- Dragging the mouse with the left button held down will
- highlight an arbitrary rectangle. Any text inside this
- rectangle will be copied to the X selection buffer.
+ Dragging the mouse with the left button held down will highlight an
+ arbitrary rectangle. Any text inside this rectangle will be copied to
+ the X selection buffer.
Links
- Clicking on a hyperlink will jump to the link's
- destination. A link to another PDF document will make
- xpdf load that document. A 'launch' link to an executable
- program will display a dialog, and if you click 'ok', exe-
- cute the program. URL links call an external command (see
- the WEB BROWSERS section below).
+ Clicking on a hyperlink will jump to the link's destination. A link to
+ another PDF document will make xpdf load that document. A 'launch'
+ link to an executable program will display a dialog, and if you click
+ 'ok', execute the program. URL links call an external command (see the
+ WEB BROWSERS section below).
Panning
- Dragging the mouse with the middle button held down pans
- the window.
+ Dragging the mouse with the middle button held down pans the window.
Key bindings
o Open a new PDF file via a file requester.
- r Reload the current PDF file. Note that Xpdf will
- reload the file automatically (on a page change or
- redraw) if it has changed since it was last loaded.
+ r Reload the current PDF file. Note that Xpdf will reload the
+ file automatically (on a page change or redraw) if it has
+ changed since it was last loaded.
control-L
Redraw the current page.
@@ -362,19 +327,19 @@ CONTROLS
control-P
Print.
- n Move to the next page. Scrolls to the top of the
- page, unless scroll lock is turned on.
+ n Move to the next page. Scrolls to the top of the page, unless
+ scroll lock is turned on.
- p Move to the previous page. Scrolls to the top of
- the page, unless scroll lock is turned on.
+ p Move to the previous page. Scrolls to the top of the page,
+ unless scroll lock is turned on.
<Space> or <PageDown> or <Next>
- Scroll down on the current page; if already at bot-
- tom, move to next page.
+ Scroll down on the current page; if already at bottom, move to
+ next page.
<Backspace> or <Delete> or <PageUp> or <Previous>
- Scroll up on the current page; if already at top,
- move to previous page.
+ Scroll up on the current page; if already at top, move to previ-
+ ous page.
v Move forward along the history path.
@@ -392,7 +357,7 @@ CONTROLS
arrows Scroll the current page.
- g Activate the page number text field ("goto page").
+ g Activate the page number text field ("goto page").
0 Set the zoom factor to 125%.
@@ -402,19 +367,17 @@ CONTROLS
z Set the zoom factor to 'page' (fit page to window).
- w Set the zoom factor to 'width' (fit page width to
- window).
+ w Set the zoom factor to 'width' (fit page width to window).
alt-F Toggle full-screen mode.
q Quit xpdf.
WEB BROWSERS
- If you want to run xpdf automatically from netscape or
- mosaic (and probably other browsers) when you click on a
- link to a PDF file, you need to edit (or create) the files
- .mime.types and .mailcap in your home directory. In
- .mime.types add the line:
+ If you want to run xpdf automatically from netscape or mosaic (and
+ probably other browsers) when you click on a link to a PDF file, you
+ need to edit (or create) the files .mime.types and .mailcap in your
+ home directory. In .mime.types add the line:
application/pdf pdf
@@ -425,19 +388,18 @@ WEB BROWSERS
Make sure that xpdf is on your executable search path.
- When you click on a URL link in a PDF file, xpdf will exe-
- cute the command specified by the urlCommand config file
- option, replacing an occurrence of '%s' with the URL. For
- example, to call netscape with the URL, add this line to
- your config file:
+ When you click on a URL link in a PDF file, xpdf will execute the com-
+ mand specified by the urlCommand config file option, replacing an
+ occurrence of '%s' with the URL. For example, to call netscape with
+ the URL, add this line to your config file:
urlCommand "netscape -remote 'openURL(%s)'"
COMMANDS
- Xpdf's key and mouse bindings are user-configurable, using
- the bind and unbind options in the config file (see
- xpdfrc(5)). The bind command allows you to bind a key or
- mouse button to a sequence of one or more commands.
+ Xpdf's key and mouse bindings are user-configurable, using the bind and
+ unbind options in the config file (see xpdfrc(5)). The bind command
+ allows you to bind a key or mouse button to a sequence of one or more
+ commands.
Available Commands
The following commands are supported:
@@ -446,8 +408,8 @@ COMMANDS
Go to the specified page.
gotoPageNoScroll(page)
- Go to the specified page, with the current relative
- scroll position.
+ Go to the specified page, with the current relative scroll posi-
+ tion.
gotoDest(dest)
Go to a named destination.
@@ -456,22 +418,21 @@ COMMANDS
Go to the last page in the PDF file.
gotoLastPageNoScroll
- Go to the last page in the PDF file, with the cur-
- rent relative scroll position.
+ Go to the last page in the PDF file, with the current relative
+ scroll position.
nextPage
Go to the next page.
nextPageNoScroll
- Go to the next page, with the current relative
- scroll position.
+ Go to the next page, with the current relative scroll position.
prevPage
Go to the previous page.
prevPageNoScroll
- Go to the previous page, with the current relative
- scroll position.
+ Go to the previous page, with the current relative scroll posi-
+ tion.
pageUp Scroll up by one screenful.
@@ -491,35 +452,33 @@ COMMANDS
Scroll down by n pixels.
scrollUpPrevPage(n)
- Scroll up by n pixels, moving to the previous page
- if appropriate.
+ Scroll up by n pixels, moving to the previous page if appropri-
+ ate.
scrollDownPrevPage(n)
- Scroll down by n pixels, moving to the next page if
- appropriate.
+ Scroll down by n pixels, moving to the next page if appropriate.
scrollToTopEdge
- Scroll to the top edge of the current page, with no
- horizontal movement.
+ Scroll to the top edge of the current page, with no horizontal
+ movement.
scrollToBottomEdge
- Scroll to the bottom edge of the current page, with
- no horizontal movement.
+ Scroll to the bottom edge of the current page, with no horizon-
+ tal movement.
scrollToLeftEdge
- Scroll to the left edge of the current page, with
- no vertical movement.
+ Scroll to the left edge of the current page, with no vertical
+ movement.
scrollToRightEdge
- Scroll to the right edge of the current page, with
- no vertical movement.
+ Scroll to the right edge of the current page, with no vertical
+ movement.
scrollToTopLeft
- Scroll to the top-left corner of the current page.
+ Scroll to the top-left corner of the current page.
scrollToBottomRight
- Scroll to the bottom-right corner of the current
- page.
+ Scroll to the bottom-right corner of the current page.
goForward
Move forward along the history path.
@@ -541,6 +500,16 @@ COMMANDS
zoomOut
Zoom out - go the next lower zoom factor.
+ rotateCW
+ Rotate the page 90 degrees clockwise.
+
+ rotateCCW
+ Rotate the page 90 degrees counterclockwise.
+
+ setSelection(pg,ulx,uly,lrx,lry)
+ Set the selection to the specified coordinates on the specified
+ page.
+
continuousMode
Go to continuous view mode.
@@ -548,8 +517,7 @@ COMMANDS
Go to single-page view mode.
toggleContinuousMode
- Toggle between continuous and single page view
- modes.
+ Toggle between continuous and single page view modes.
fullScreenMode
Go to full-screen mode.
@@ -560,12 +528,10 @@ COMMANDS
toggleFullScreenMode
Toggle between full-screen and window modes.
- open Open a PDF file in this window, using the open dia-
- log.
+ open Open a PDF file in this window, using the open dialog.
openInNewWin
- Open a PDF file in a new window, using the open
- dialog.
+ Open a PDF file in a new window, using the open dialog.
openFile(file)
Open a specified PDF file in this window.
@@ -574,12 +540,12 @@ COMMANDS
Open a specified PDF file in a new window.
openFileAtDest(file,dest)
- Open a specified PDF file in this window and go to
- a named destination.
+ Open a specified PDF file in this window and go to a named des-
+ tination.
openFileAtDestInNewWin(file,dest)
- Open a specified PDF file in a new window and go to
- a named destination.
+ Open a specified PDF file in a new window and go to a named des-
+ tination.
reload Reload the current PDF file.
@@ -591,8 +557,8 @@ COMMANDS
Close the window.
run(external-command-string)
- Run an external command. The following escapes are
- allowed in the command string:
+ Run an external command. The following escapes are allowed in
+ the command string:
%f => PDF file name (or an empty string if no
file is open)
@@ -601,6 +567,8 @@ COMMANDS
file is open)
%u => link URL (or an empty string if not over
a URL link)
+ %p => current page number (or an empty string if
+ no file is open)
%x => selection upper-left x coordinate
(or 0 if there is no selection)
%y => selection upper-left y coordinate
@@ -609,6 +577,9 @@ COMMANDS
(or 0 if there is no selection)
%Y => selection lower-right y coordinate
(or 0 if there is no selection)
+ %i => page containing the mouse pointer
+ %j => x coordinate of the mouse pointer
+ %k => y coordinate of the mouse pointer
%% => %
@@ -636,8 +607,7 @@ COMMANDS
find Open the 'find' dialog.
findNext
- Finds the next occurrence of the search string (no
- dialog).
+ Finds the next occurrence of the search string (no dialog).
print Open the 'print' dialog.
@@ -645,19 +615,16 @@ COMMANDS
quit Quit from xpdf.
- The following commands depend on the current mouse posi-
- tion:
+ The following commands depend on the current mouse position:
startSelection
- Start a selection, which will be extended as the
- mouse moves.
+ Start a selection, which will be extended as the mouse moves.
endSelection
End a selection.
startPan
- Start a pan, which will scroll the document as the
- mouse moves
+ Start a pan, which will scroll the document as the mouse moves
endPan End a pan.
@@ -665,24 +632,21 @@ COMMANDS
Display the popup menu.
followLink
- Follow a hyperlink (does nothing if the mouse is
- not over a link).
+ Follow a hyperlink (does nothing if the mouse is not over a
+ link).
followLinkInNewWin
- Follow a hyperlink, opening PDF files in a new win-
- dow (does nothing if the mouse is not over a link).
- For links to non-PDF files, this command is identi-
- cal to followLink.
+ Follow a hyperlink, opening PDF files in a new window (does
+ nothing if the mouse is not over a link). For links to non-PDF
+ files, this command is identical to followLink.
followLinkNoSel
- Same as followLink, but does nothing if there is a
- non-empty selection. (This is useful as a mouse
- button binding.)
+ Same as followLink, but does nothing if there is a non-empty
+ selection. (This is useful as a mouse button binding.)
followLinkInNewWinNoSel
- Same as followLinkInNewWin, but does nothing if
- there is a non-empty selection. (This is useful as
- a mouse button binding.)
+ Same as followLinkInNewWin, but does nothing if there is a non-
+ empty selection. (This is useful as a mouse button binding.)
Default Bindings
The default mouse bindings are as follows:
@@ -744,9 +708,8 @@ COMMANDS
bind q any quit
bind Q any quit
- Previous versions of xpdf included a "viKeys" X resource.
- It is no longer available, but the following bindings are
- equivalent:
+ Previous versions of xpdf included a "viKeys" X resource. It is no
+ longer available, but the following bindings are equivalent:
bind h any scrollLeft(16)
bind l any scrollRight(16)
@@ -755,32 +718,28 @@ COMMANDS
REMOTE SERVER MODE
- Xpdf can be started in remote server mode by specifying a
- server name (in addition to the file name and page num-
- ber). For example:
+ Xpdf can be started in remote server mode by specifying a server name
+ (in addition to the file name and page number). For example:
xpdf -remote myServer file.pdf
- If there is currently no xpdf running in server mode with
- the name 'myServer', a new xpdf window will be opened. If
- another command:
+ If there is currently no xpdf running in server mode with the name
+ 'myServer', a new xpdf window will be opened. If another command:
xpdf -remote myServer another.pdf 9
- is issued, a new copy of xpdf will not be started.
- Instead, the first xpdf (the server) will load another.pdf
- and display page nine. If the file name is the same:
+ is issued, a new copy of xpdf will not be started. Instead, the first
+ xpdf (the server) will load another.pdf and display page nine. If the
+ file name is the same:
xpdf -remote myServer another.pdf 4
the xpdf server will simply display the specified page.
- The -raise option tells the server to raise its window; it
- can be specified with or without a file name and page num-
- ber.
+ The -raise option tells the server to raise its window; it can be spec-
+ ified with or without a file name and page number.
- The -quit option tells the server to close its window and
- exit.
+ The -quit option tells the server to close its window and exit.
EXIT CODES
The Xpdf tools use the following exit codes:
@@ -796,14 +755,14 @@ EXIT CODES
99 Other error.
AUTHOR
- The xpdf software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The xpdf software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- 27 February 2007 xpdf(1)
+ 15 August 2011 xpdf(1)
diff --git a/doc/xpdf.hlp b/doc/xpdf.hlp
index 1f90bab..9696ec7 100644
--- a/doc/xpdf.hlp
+++ b/doc/xpdf.hlp
@@ -1,237 +1,210 @@
! Generated automatically by mantohlp
1 xpdf
- xpdf - Portable Document Format (PDF) file viewer for X
- (version 3.02)
+ xpdf - Portable Document Format (PDF) file viewer for X (version 3.03)
xpdf [options] [PDF-file [page | +dest]]
- Xpdf is a viewer for Portable Document Format (PDF) files.
- (These are also sometimes also called 'Acrobat' files,
- from the name of Adobe's PDF software.) Xpdf runs under
- the X Window System on UNIX, VMS, and OS/2.
+ Xpdf is a viewer for Portable Document Format (PDF) files. (These are
+ also sometimes also called 'Acrobat' files, from the name of Adobe's
+ PDF software.) Xpdf runs under the X Window System on UNIX, VMS, and
+ OS/2.
To run xpdf, simply type:
xpdf file.pdf
- where file.pdf is your PDF file. The file name can be
- followed by a number specifying the page which should be
- displayed first, e.g.:
+ where file.pdf is your PDF file. The file name can be followed by a
+ number specifying the page which should be displayed first, e.g.:
xpdf file.pdf 18
- You can also give a named destination, prefixed with '+'
- in place of the page number. (This is only useful with
- PDF files that provide named destination targets.)
+ You can also give a named destination, prefixed with '+' in place of
+ the page number. (This is only useful with PDF files that provide
+ named destination targets.)
You can also start xpdf without opening any files:
xpdf
- ()
+ ()
2 ONFIGURATION_FIL
- Xpdf reads a configuration file at startup. It first
- tries to find the user's private config file, ~/.xpdfrc.
- If that doesn't exist, it looks for a system-wide config
- file, typically /usr/local/etc/xpdfrc (but this location
- can be changed when xpdf is built). See the xpdfrc(5) man
- page for details.
+ Xpdf reads a configuration file at startup. It first tries to find the
+ user's private config file, ~/.xpdfrc. If that doesn't exist, it looks
+ for a system-wide config file, typically /usr/local/etc/xpdfrc (but
+ this location can be changed when xpdf is built). See the xpdfrc(5)
+ man page for details.
- ()
+ ()
2 OPTIONS
- Many of the following options can be set with configura-
- tion file commands or X resources. These are listed in
- square brackets with the description of the corresponding
- command line option.
+ Many of the following options can be set with configuration file com-
+ mands or X resources. These are listed in square brackets with the
+ description of the corresponding command line option.
-g geometry
- Set the initial window geometry. (-geometry is
- equivalent.) [X resource: xpdf.geometry]
+ Set the initial window geometry. (-geometry is equivalent.) [X
+ resource: xpdf.geometry]
-title title
- Set the window title. By default, the title will
- be "xpdf: foo.pdf". [X resource: xpdf.title]
+ Set the window title. By default, the title will be "xpdf:
+ foo.pdf". [X resource: xpdf.title]
- -cmap Install a private colormap. This is ignored on
- TrueColor visuals. [X resource: xpdf.installCmap]
+ -cmap Install a private colormap. This is ignored on TrueColor visu-
+ als. [X resource: xpdf.installCmap]
-rgb number
- Set the size of largest RGB cube xpdf will try to
- allocate. The default is 5 (for a 5x5x5 cube); set
- to a smaller number to conserve color table
- entries. This is ignored with private colormaps
- and on TrueColor visuals. [X resource:
- xpdf.rgbCubeSize]
-
- -rv Set reverse video mode. This reverses the colors
- of everything except images. It may not always
- produce great results for PDF files which do weird
- things with color. This also causes the paper
- color to default to black. [X resource:
- xpdf.reverseVideo]
+ Set the size of largest RGB cube xpdf will try to allocate. The
+ default is 5 (for a 5x5x5 cube); set to a smaller number to con-
+ serve color table entries. This is ignored with private col-
+ ormaps and on TrueColor visuals. [X resource: xpdf.rgbCubeSize]
+
+ -rv Set reverse video mode. This reverses the colors of everything
+ except images. It may not always produce great results for PDF
+ files which do weird things with color. This also causes the
+ paper color to default to black. [X resource: xpdf.reverseV-
+ ideo]
-papercolor color
- Set the "paper color", i.e., the background of the
- page display. This will not work too well with PDF
- files that do things like filling in white behind
- the text. [X resource: xpdf.paperColor]
+ Set the "paper color", i.e., the background of the page display.
+ This will not work too well with PDF files that do things like
+ filling in white behind the text. [X resource: xpdf.paperColor]
-mattecolor color
- Set the matte color, i.e., the color used for back-
- ground outside the actual page area. (There is a
- separate setting, xpdf.fullScreenMatteColor, for
- full-screen mode.) [X resource: xpdf.matteColor]
+ Set the matte color, i.e., the color used for background outside
+ the actual page area. (There is a separate setting,
+ xpdf.fullScreenMatteColor, for full-screen mode.) [X resource:
+ xpdf.matteColor]
-z zoom
- Set the initial zoom factor. A number specifies a
- zoom percentage, where 100 means 72 dpi.You may
- also specify 'page', to fit the page to the window
- size, or 'width', to fit the page width to the win-
- dow width. [config file: initialZoom; or X
+ Set the initial zoom factor. A number specifies a zoom percent-
+ age, where 100 means 72 dpi. You may also specify 'page', to
+ fit the page to the window size, or 'width', to fit the page
+ width to the window width. [config file: initialZoom; or X
resource: xpdf.initialZoom]
- -cont Start in continuous view mode, i.e., with one ver-
- tical scroll bar for the whole document. [config
- file: continuousView]
+ -cont Start in continuous view mode, i.e., with one vertical scroll
+ bar for the whole document. [config file: continuousView]
-t1lib yes | no
- Enable or disable t1lib (a Type 1 font rasterizer).
- This defaults to "yes". [config file: enableT1lib]
+ Enable or disable t1lib (a Type 1 font rasterizer). This
+ defaults to "yes". [config file: enableT1lib]
-freetype yes | no
- Enable or disable FreeType (a TrueType / Type 1
- font rasterizer). This defaults to "yes". [config
- file: enableFreeType]
+ Enable or disable FreeType (a TrueType / Type 1 font raster-
+ izer). This defaults to "yes". [config file: enableFreeType]
-aa yes | no
- Enable or disable font anti-aliasing. This
- defaults to "yes". [config file: antialias]
+ Enable or disable font anti-aliasing. This defaults to "yes".
+ [config file: antialias]
-aaVector yes | no
- Enable or disable vector anti-aliasing. This
- defaults to "yes". [config file: vectorAntialias]
+ Enable or disable vector anti-aliasing. This defaults to "yes".
+ [config file: vectorAntialias]
-ps PS-file
- Set the default file name for PostScript output
- (i.e., the name which will appear in the print dia-
- log). This can also be of the form '|command' to
- pipe the PostScript through a command. [config
- file: psFile]
+ Set the default file name for PostScript output (i.e., the name
+ which will appear in the print dialog). This can also be of the
+ form '|command' to pipe the PostScript through a command. [con-
+ fig file: psFile]
-paper size
- Set the paper size to one of "letter", "legal",
- "A4", or "A3". This can also be set to "match",
- which will set the paper size to match the size
- specified in the PDF file. [config file: psPaper-
- Size]
+ Set the paper size to one of "letter", "legal", "A4", or "A3".
+ This can also be set to "match", which will set the paper size
+ to match the size specified in the PDF file. [config file:
+ psPaperSize]
-paperw size
- Set the paper width, in points. [config file:
- psPaperSize]
+ Set the paper width, in points. [config file: psPaperSize]
-paperh size
- Set the paper height, in points. [config file:
- psPaperSize]
+ Set the paper height, in points. [config file: psPaperSize]
-level1
- Generate Level 1 PostScript. The resulting
- PostScript files will be significantly larger (if
- they contain images), but will print on Level 1
- printers. This also converts all images to black
- and white. [config file: psLevel]
+ Generate Level 1 PostScript. The resulting PostScript files
+ will be significantly larger (if they contain images), but will
+ print on Level 1 printers. This also converts all images to
+ black and white. [config file: psLevel]
-enc encoding-name
- Sets the encoding to use for text output. The
- encoding-name must be defined with the unicodeMap
- command (see xpdfrc(5)). This defaults to "Latin1"
- (which is a built-in encoding). [config file: tex-
- tEncoding]
+ Sets the encoding to use for text output. The encoding-name
+ must be defined with the unicodeMap command (see xpdfrc(5)).
+ This defaults to "Latin1" (which is a built-in encoding). [con-
+ fig file: textEncoding]
-eol unix | dos | mac
- Sets the end-of-line convention to use for text
- output. [config file: textEOL]
+ Sets the end-of-line convention to use for text output. [config
+ file: textEOL]
-opw password
- Specify the owner password for the PDF file. Pro-
- viding this will bypass all security restrictions.
+ Specify the owner password for the PDF file. Providing this
+ will bypass all security restrictions.
-upw password
Specify the user password for the PDF file.
-fullscreen
- Open xpdf in full-screen mode, useful for presenta-
- tions.
+ Open xpdf in full-screen mode, useful for presentations.
-remote name
- Start/contact xpdf remote server with specified
- name (see the REMOTE SERVER MODE section below).
+ Start/contact xpdf remote server with specified name (see the
+ REMOTE SERVER MODE section below).
-exec command
- Execute a command (see the COMMANDS section below)
- in an xpdf remote server window (with -remote
- only).
+ Execute a command (see the COMMANDS section below) in an xpdf
+ remote server window (with -remote only).
-reload
- Reload xpdf remote server window (with -remote
- only).
+ Reload xpdf remote server window (with -remote only).
- -raise Raise xpdf remote server window (with -remote
- only).
+ -raise Raise xpdf remote server window (with -remote only).
-quit Kill xpdf remote server (with -remote only).
- -cmd Print commands as they're executed (useful for
- debugging). [config file: printCommands]
+ -cmd Print commands as they're executed (useful for debugging).
+ [config file: printCommands]
- -q Don't print any messages or errors. [config file:
- errQuiet]
+ -q Don't print any messages or errors. [config file: errQuiet]
-cfg config-file
- Read config-file in place of ~/.xpdfrc or the sys-
- tem-wide config file.
+ Read config-file in place of ~/.xpdfrc or the system-wide config
+ file.
-v Print copyright and version information.
- -h Print usage information. (-help and --help are
- equivalent.)
+ -h Print usage information. (-help and --help are equivalent.)
- Several other standard X options and resources will work
- as expected:
+ Several other standard X options and resources will work as expected:
-display display
[X resource: xpdf.display]
-fg color
- (-foreground is equivalent.) [X resource:
- xpdf*Foreground]
+ (-foreground is equivalent.) [X resource: xpdf*Foreground]
-bg color
- (-background is equivalent.) [X resource:
- xpdf*Background]
+ (-background is equivalent.) [X resource: xpdf*Background]
-font font
(-fn is equivalent.) [X resource: xpdf*fontList]
- The color and font options only affect the user interface
- elements, not the PDF display (the 'paper').
+ The color and font options only affect the user interface elements, not
+ the PDF display (the 'paper').
- The following X resources do not have command line option
- equivalents:
+ The following X resources do not have command line option equivalents:
xpdf.toolTipEnable
- Enables (if set to true) or disables (if set to
- false) the tool-tips on the toolbar buttons.
+ Enables (if set to true) or disables (if set to false) the tool-
+ tips on the toolbar buttons.
xpdf.fullScreenMatteColor
- Sets the matte color to be used in full-screen
- mode. The default setting is "black".
+ Sets the matte color to be used in full-screen mode. The
+ default setting is "black".
- ()
+ ()
2 CONTROLS
@@ -246,105 +219,97 @@
Move backward or forward along the history path.
'Page' entry box
- Move to a specific page number. Click in the box
- to activate it, type the page number, then hit
- return.
+ Move to a specific page number. Click in the box to activate
+ it, type the page number, then hit return.
zoom popup menu
- Change the zoom factor (see the description of the
- -z option above).
+ Change the zoom factor (see the description of the -z option
+ above).
binoculars button
Find a text string.
print button
- Bring up a dialog for generating a PostScript file.
- The dialog has options to set the pages to be
- printed and the PostScript file name. The file
- name can be '-' for stdout or '|command' to pipe
- the PostScript through a command, e.g., '|lpr'.
+ Bring up a dialog for generating a PostScript file. The dialog
+ has options to set the pages to be printed and the PostScript
+ file name. The file name can be '-' for stdout or '|command' to
+ pipe the PostScript through a command, e.g., '|lpr'.
'?' button
Bring up the 'about xpdf' window.
link info
- The space between the '?' and 'Quit' buttons is
- used to show the URL or external file name when the
- mouse is over a link.
+ The space between the '?' and 'Quit' buttons is used to show the
+ URL or external file name when the mouse is over a link.
'Quit' button
Quit xpdf.
Menu
- Pressing the right mouse button will post a popup menu
- with the following commands:
+ Pressing the right mouse button will post a popup menu with the follow-
+ ing commands:
Open...
Open a new PDF file via a file requester.
Open in new window...
- Create a new window and open a new PDF file via a
- file requester.
+ Create a new window and open a new PDF file via a file
+ requester.
- Reload Reload the current PDF file. Note that Xpdf will
- reload the file automatically (on a page change or
- redraw) if it has changed since it was last loaded.
+ Reload Reload the current PDF file. Note that Xpdf will reload the
+ file automatically (on a page change or redraw) if it has
+ changed since it was last loaded.
Save as...
Save the current file via a file requester.
Continuous view
- Toggles between single page and continuous view
- modes.
+ Toggles between single page and continuous view modes.
Rotate counterclockwise
Rotate the page 90 degrees counterclockwise.
Rotate clockwise
- Rotate the page 90 degrees clockwise. The two
- rotate commands are intended primarily for PDF
- files where the rotation isn't correctly specified
- in the file.
+ Rotate the page 90 degrees clockwise. The two rotate commands
+ are intended primarily for PDF files where the rotation isn't
+ correctly specified in the file.
Zoom to selection
Zoom in to the currently selected rectangle.
- Close Close the current window. If this is the only open
- window, the document is closed, but the window is
- left open (i.e., this menu command won't quit
- xpdf).
+ Close Close the current window. If this is the only open window, the
+ document is closed, but the window is left open (i.e., this menu
+ command won't quit xpdf).
Quit Quit xpdf.
Outline
- If the PDF contains an outline (a.k.a., bookmarks), there
- will be an outline pane on the left side of the window.
- The width of the outline pane is adjustable with a verti-
- cal split bar via the knob near its bottom end.
+ If the PDF contains an outline (a.k.a., bookmarks), there will be an
+ outline pane on the left side of the window. The width of the outline
+ pane is adjustable with a vertical split bar via the knob near its bot-
+ tom end.
Text selection
- Dragging the mouse with the left button held down will
- highlight an arbitrary rectangle. Any text inside this
- rectangle will be copied to the X selection buffer.
+ Dragging the mouse with the left button held down will highlight an
+ arbitrary rectangle. Any text inside this rectangle will be copied to
+ the X selection buffer.
Links
- Clicking on a hyperlink will jump to the link's destina-
- tion. A link to another PDF document will make xpdf load
- that document. A 'launch' link to an executable program
- will display a dialog, and if you click 'ok', execute the
- program. URL links call an external command (see the WEB
- BROWSERS section below).
+ Clicking on a hyperlink will jump to the link's destination. A link to
+ another PDF document will make xpdf load that document. A 'launch'
+ link to an executable program will display a dialog, and if you click
+ 'ok', execute the program. URL links call an external command (see the
+ WEB BROWSERS section below).
Panning
- Dragging the mouse with the middle button held down pans
- the window.
+ Dragging the mouse with the middle button held down pans the window.
Key bindings
o Open a new PDF file via a file requester.
- r Reload the current PDF file. Note that Xpdf will
- reload the file automatically (on a page change or
- redraw) if it has changed since it was last loaded.
+ r Reload the current PDF file. Note that Xpdf will reload the
+ file automatically (on a page change or redraw) if it has
+ changed since it was last loaded.
control-L
Redraw the current page.
@@ -361,19 +326,19 @@
control-P
Print.
- n Move to the next page. Scrolls to the top of the
- page, unless scroll lock is turned on.
+ n Move to the next page. Scrolls to the top of the page, unless
+ scroll lock is turned on.
- p Move to the previous page. Scrolls to the top of
- the page, unless scroll lock is turned on.
+ p Move to the previous page. Scrolls to the top of the page,
+ unless scroll lock is turned on.
<Space> or <PageDown> or <Next>
- Scroll down on the current page; if already at bot-
- tom, move to next page.
+ Scroll down on the current page; if already at bottom, move to
+ next page.
<Backspace> or <Delete> or <PageUp> or <Previous>
- Scroll up on the current page; if already at top,
- move to previous page.
+ Scroll up on the current page; if already at top, move to previ-
+ ous page.
v Move forward along the history path.
@@ -391,7 +356,7 @@
arrows Scroll the current page.
- g Activate the page number text field ("goto page").
+ g Activate the page number text field ("goto page").
0 Set the zoom factor to 125%.
@@ -401,22 +366,20 @@
z Set the zoom factor to 'page' (fit page to window).
- w Set the zoom factor to 'width' (fit page width to
- window).
+ w Set the zoom factor to 'width' (fit page width to window).
alt-F Toggle full-screen mode.
q Quit xpdf.
- ()
+ ()
2 WEB_BROWSERS
- If you want to run xpdf automatically from netscape or
- mosaic (and probably other browsers) when you click on a
- link to a PDF file, you need to edit (or create) the files
- .mime.types and .mailcap in your home directory. In
- .mime.types add the line:
+ If you want to run xpdf automatically from netscape or mosaic (and
+ probably other browsers) when you click on a link to a PDF file, you
+ need to edit (or create) the files .mime.types and .mailcap in your
+ home directory. In .mime.types add the line:
application/pdf pdf
@@ -427,22 +390,21 @@
Make sure that xpdf is on your executable search path.
- When you click on a URL link in a PDF file, xpdf will exe-
- cute the command specified by the urlCommand config file
- option, replacing an occurrence of '%s' with the URL. For
- example, to call netscape with the URL, add this line to
- your config file:
+ When you click on a URL link in a PDF file, xpdf will execute the com-
+ mand specified by the urlCommand config file option, replacing an
+ occurrence of '%s' with the URL. For example, to call netscape with
+ the URL, add this line to your config file:
urlCommand "netscape -remote 'openURL(%s)'"
- ()
+ ()
2 COMMANDS
- Xpdf's key and mouse bindings are user-configurable, using
- the bind and unbind options in the config file (see
- xpdfrc(5)). The bind command allows you to bind a key or
- mouse button to a sequence of one or more commands.
+ Xpdf's key and mouse bindings are user-configurable, using the bind and
+ unbind options in the config file (see xpdfrc(5)). The bind command
+ allows you to bind a key or mouse button to a sequence of one or more
+ commands.
Available Commands
The following commands are supported:
@@ -451,8 +413,8 @@
Go to the specified page.
gotoPageNoScroll(page)
- Go to the specified page, with the current relative
- scroll position.
+ Go to the specified page, with the current relative scroll posi-
+ tion.
gotoDest(dest)
Go to a named destination.
@@ -461,22 +423,21 @@
Go to the last page in the PDF file.
gotoLastPageNoScroll
- Go to the last page in the PDF file, with the cur-
- rent relative scroll position.
+ Go to the last page in the PDF file, with the current relative
+ scroll position.
nextPage
Go to the next page.
nextPageNoScroll
- Go to the next page, with the current relative
- scroll position.
+ Go to the next page, with the current relative scroll position.
prevPage
Go to the previous page.
prevPageNoScroll
- Go to the previous page, with the current relative
- scroll position.
+ Go to the previous page, with the current relative scroll posi-
+ tion.
pageUp Scroll up by one screenful.
@@ -496,35 +457,33 @@
Scroll down by n pixels.
scrollUpPrevPage(n)
- Scroll up by n pixels, moving to the previous page
- if appropriate.
+ Scroll up by n pixels, moving to the previous page if appropri-
+ ate.
scrollDownPrevPage(n)
- Scroll down by n pixels, moving to the next page if
- appropriate.
+ Scroll down by n pixels, moving to the next page if appropriate.
scrollToTopEdge
- Scroll to the top edge of the current page, with no
- horizontal movement.
+ Scroll to the top edge of the current page, with no horizontal
+ movement.
scrollToBottomEdge
- Scroll to the bottom edge of the current page, with
- no horizontal movement.
+ Scroll to the bottom edge of the current page, with no horizon-
+ tal movement.
scrollToLeftEdge
- Scroll to the left edge of the current page, with
- no vertical movement.
+ Scroll to the left edge of the current page, with no vertical
+ movement.
scrollToRightEdge
- Scroll to the right edge of the current page, with
- no vertical movement.
+ Scroll to the right edge of the current page, with no vertical
+ movement.
scrollToTopLeft
- Scroll to the top-left corner of the current page.
+ Scroll to the top-left corner of the current page.
scrollToBottomRight
- Scroll to the bottom-right corner of the current
- page.
+ Scroll to the bottom-right corner of the current page.
goForward
Move forward along the history path.
@@ -546,6 +505,16 @@
zoomOut
Zoom out - go the next lower zoom factor.
+ rotateCW
+ Rotate the page 90 degrees clockwise.
+
+ rotateCCW
+ Rotate the page 90 degrees counterclockwise.
+
+ setSelection(pg,ulx,uly,lrx,lry)
+ Set the selection to the specified coordinates on the specified
+ page.
+
continuousMode
Go to continuous view mode.
@@ -553,8 +522,7 @@
Go to single-page view mode.
toggleContinuousMode
- Toggle between continuous and single page view
- modes.
+ Toggle between continuous and single page view modes.
fullScreenMode
Go to full-screen mode.
@@ -565,12 +533,10 @@
toggleFullScreenMode
Toggle between full-screen and window modes.
- open Open a PDF file in this window, using the open
- dialog.
+ open Open a PDF file in this window, using the open dialog.
openInNewWin
- Open a PDF file in a new window, using the open
- dialog.
+ Open a PDF file in a new window, using the open dialog.
openFile(file)
Open a specified PDF file in this window.
@@ -579,12 +545,12 @@
Open a specified PDF file in a new window.
openFileAtDest(file,dest)
- Open a specified PDF file in this window and go to
- a named destination.
+ Open a specified PDF file in this window and go to a named des-
+ tination.
openFileAtDestInNewWin(file,dest)
- Open a specified PDF file in a new window and go to
- a named destination.
+ Open a specified PDF file in a new window and go to a named des-
+ tination.
reload Reload the current PDF file.
@@ -596,8 +562,8 @@
Close the window.
run(external-command-string)
- Run an external command. The following escapes are
- allowed in the command string:
+ Run an external command. The following escapes are allowed in
+ the command string:
%f => PDF file name (or an empty string if no
file is open)
@@ -606,6 +572,8 @@
file is open)
%u => link URL (or an empty string if not over
a URL link)
+ %p => current page number (or an empty string if
+ no file is open)
%x => selection upper-left x coordinate
(or 0 if there is no selection)
%y => selection upper-left y coordinate
@@ -614,6 +582,9 @@
(or 0 if there is no selection)
%Y => selection lower-right y coordinate
(or 0 if there is no selection)
+ %i => page containing the mouse pointer
+ %j => x coordinate of the mouse pointer
+ %k => y coordinate of the mouse pointer
%% => %
openOutline
@@ -640,8 +611,7 @@
find Open the 'find' dialog.
findNext
- Finds the next occurrence of the search string (no
- dialog).
+ Finds the next occurrence of the search string (no dialog).
print Open the 'print' dialog.
@@ -649,19 +619,16 @@
quit Quit from xpdf.
- The following commands depend on the current mouse posi-
- tion:
+ The following commands depend on the current mouse position:
startSelection
- Start a selection, which will be extended as the
- mouse moves.
+ Start a selection, which will be extended as the mouse moves.
endSelection
End a selection.
startPan
- Start a pan, which will scroll the document as the
- mouse moves
+ Start a pan, which will scroll the document as the mouse moves
endPan End a pan.
@@ -669,24 +636,21 @@
Display the popup menu.
followLink
- Follow a hyperlink (does nothing if the mouse is
- not over a link).
+ Follow a hyperlink (does nothing if the mouse is not over a
+ link).
followLinkInNewWin
- Follow a hyperlink, opening PDF files in a new win-
- dow (does nothing if the mouse is not over a link).
- For links to non-PDF files, this command is identi-
- cal to followLink.
+ Follow a hyperlink, opening PDF files in a new window (does
+ nothing if the mouse is not over a link). For links to non-PDF
+ files, this command is identical to followLink.
followLinkNoSel
- Same as followLink, but does nothing if there is a
- non-empty selection. (This is useful as a mouse
- button binding.)
+ Same as followLink, but does nothing if there is a non-empty
+ selection. (This is useful as a mouse button binding.)
followLinkInNewWinNoSel
- Same as followLinkInNewWin, but does nothing if
- there is a non-empty selection. (This is useful as
- a mouse button binding.)
+ Same as followLinkInNewWin, but does nothing if there is a non-
+ empty selection. (This is useful as a mouse button binding.)
Default Bindings
The default mouse bindings are as follows:
@@ -748,47 +712,42 @@
bind q any quit
bind Q any quit
- Previous versions of xpdf included a "viKeys" X resource.
- It is no longer available, but the following bindings are
- equivalent:
+ Previous versions of xpdf included a "viKeys" X resource. It is no
+ longer available, but the following bindings are equivalent:
bind h any scrollLeft(16)
bind l any scrollRight(16)
bind k any scrollUp(16)
bind j any scrollDown(16)
- ()
+ ()
2 REMOTE_SERVER_MODE
- Xpdf can be started in remote server mode by specifying a
- server name (in addition to the file name and page num-
- ber). For example:
+ Xpdf can be started in remote server mode by specifying a server name
+ (in addition to the file name and page number). For example:
xpdf -remote myServer file.pdf
- If there is currently no xpdf running in server mode with
- the name 'myServer', a new xpdf window will be opened. If
- another command:
+ If there is currently no xpdf running in server mode with the name
+ 'myServer', a new xpdf window will be opened. If another command:
xpdf -remote myServer another.pdf 9
- is issued, a new copy of xpdf will not be started.
- Instead, the first xpdf (the server) will load another.pdf
- and display page nine. If the file name is the same:
+ is issued, a new copy of xpdf will not be started. Instead, the first
+ xpdf (the server) will load another.pdf and display page nine. If the
+ file name is the same:
xpdf -remote myServer another.pdf 4
the xpdf server will simply display the specified page.
- The -raise option tells the server to raise its window; it
- can be specified with or without a file name and page num-
- ber.
+ The -raise option tells the server to raise its window; it can be spec-
+ ified with or without a file name and page number.
- The -quit option tells the server to close its window and
- exit.
+ The -quit option tells the server to close its window and exit.
- ()
+ ()
2 XIT_CODE
@@ -804,20 +763,20 @@
99 Other error.
- ()
+ ()
2 AUTHOR
- The xpdf software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The xpdf software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1),
+ pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1),
pdftoppm(1), pdfimages(1), xpdfrc(5)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/doc/xpdfrc.5 b/doc/xpdfrc.5
index 4e15455..676ad49 100644
--- a/doc/xpdfrc.5
+++ b/doc/xpdfrc.5
@@ -1,7 +1,7 @@
-.\" Copyright 2002-2007 Glyph & Cog, LLC
-.TH xpdfrc 5 "27 February 2007"
+.\" Copyright 2002-2011 Glyph & Cog, LLC
+.TH xpdfrc 5 "15 August 2011"
.SH NAME
-xpdfrc \- configuration file for Xpdf tools (version 3.02)
+xpdfrc \- configuration file for Xpdf tools (version 3.03)
.SH DESCRIPTION
All of the Xpdf tools read a single configuration file. If you have a
.I .xpdfrc
@@ -81,10 +81,9 @@ will be converted to the specified output sequence.
.BI unicodeMap " encoding\-name map\-file"
Specifies the file with mapping from Unicode to
.IR encoding\-name .
-These encodings are used for X display fonts and text output (see
-below). Each line of a unicodeMap file represents a range of one or
-more Unicode characters which maps linearly to a range in the output
-encoding:
+These encodings are used for text output (see below). Each line of a
+unicodeMap file represents a range of one or more Unicode characters
+which maps linearly to a range in the output encoding:
.nf
.I " " in\-start\-hex in\-end\-hex out\-start\-hex
@@ -137,59 +136,100 @@ Specifies a search directory,
.IR dir ,
for ToUnicode CMaps. There can be multiple ToUnicode directories.
There are no default ToUnicode directories.
-.SH DISPLAY FONTS
+.SH GENERAL FONT CONFIGURATION
.TP
-.BI displayFontT1 " PDF\-font\-name T1\-file"
+.BI fontFile " PDF\-font\-name font\-file"
Maps a PDF font,
.IR PDF\-font\-name ,
-to a Type 1 font for display. The Type 1 font file,
-.IR T1\-file ,
-should be a standard .pfa or .pfb file.
+to a font for display or PostScript output. The font file,
+.IR font\-file ,
+can be any type allowed in a PDF file. This command can be used for
+8-bit or 16-bit (CID) fonts.
.TP
-.BI displayFontTT " PDF\-font\-name TT\-file"
-Maps a PDF font,
-.IR PDF\-font\-name ,
-to a TrueType font for display. The TrueType font file,
-.IR TT\-file ,
-should be a standard .ttf file.
-.TP
-.BI displayNamedCIDFontT1 " PDF\-font\-name T1\-file"
-Maps a specific PDF CID (16-bit) font,
-.IR PDF\-font\-name ,
-to a CID font (16-bit PostScript font), for display. There are no
-default CID font mappings.
-.TP
-.BI displayCIDFontT1 " registry\-ordering T1\-file"
+.BI fontDir " dir"
+Specifies a search directory for font files. There can be multiple
+fontDir commands; all of the specified directories will be searched in
+order. The font files can be Type 1 (.pfa or .pfb) or TrueType (.ttf
+or .ttc); other files in the directory will be ignored. The font file
+name (not including the extension) must exactly match the PDF font
+name. This search is performed if the font name doesn't match any of
+the fonts declared with the fontFile command. There are no default
+fontDir directories.
+.TP
+.BI fontFileCC " registry\-ordering font\-file"
Maps the
.I registry\-ordering
-character collection to a CID font (16-bit PostScript font), for
-display. This mapping is used if the font name doesn't match any of
-the fonts declared with displayNamedCIDFont* commands. There are no
-default CID font mappings.
+character collection to a font for display or PostScript output. This
+mapping is used if the font name doesn't match any of the fonts
+declared with the fontFile, fontDir, psResidentFont16, or
+psResidentFontCC commands.
+.SH POSTSCRIPT FONT CONFIGURATION
+.TP
+.BR psFontPassthrough " yes | no"
+If set to "yes", pass 8-bit font names through to the PostScript
+output without substitution. Fonts which are not embedded in the PDF
+file are expected to be available on the printer. This defaults to
+"no".
.TP
-.BI displayNamedCIDFontTT " PDF\-font\-name TT\-file"
-Maps a specific PDF CID (16-bit) font,
-.IR PDF\-font\-name ,
-to a (16-bit) TrueType font, for display. There are no default CID
-font mappings.
+.BI psResidentFont " PDF\-font\-name PS\-font\-name"
+When the 8-bit font
+.I PDF\-font\-name
+is used (without embedding) in a PDF file, it will be translated to
+the PostScript font
+.IR PS\-font\-name ,
+which is assumed to be resident in the printer. Typically,
+.I PDF\-font\-name
+and
+.I PS\-font\-name
+are the same. By default, only the Base-14 fonts are assumed to be
+resident.
.TP
-.BI displayCIDFontTT " registry\-ordering TT\-file"
-Maps the
+.BI psResidentFont16 " PDF\-font\-name wMode PS\-font\-name encoding"
+When the 16-bit (CID) font
+.I PDF\-font\-name
+with writing mode
+.I wMode
+is used (without embedding) in a PDF file, it will be translated to
+the PostScript font
+.IR PS\-font\-name ,
+which is assumbed to be resident in the printer. The writing mode
+must be either \'H' for horizontal or \'V' for vertical. The resident
+font is assumed to use the specified encoding (which must have been
+defined with the unicodeMap command).
+.TP
+.BI psResidentFontCC " registry\-ordering wMode PS\-font\-name encoding"
+When a 16-bit (CID) font using the
.I registry\-ordering
-character collection to a (16-bit) TrueType font, for display. This
-mapping is used if the font name doesn't match any of the fonts
-declared with displayNamedCIDFont* commands. There are no default CID
-font mappings.
+character collection and
+.I wMode
+writing mode is used (without embedding) in a PDF file, the PostScript
+font,
+.IR PS\-font\-name ,
+is substituted for it. The substituted font is assumbed to be
+resident in the printer. The writing mode must be either \'H' for
+horizontal or \'V' for vertical. The resident font is assumed to use
+the specified encoding (which must have been defined with the
+unicodeMap command).
.TP
-.BI fontDir " dir"
-Specifies a search directory for external font files. There can be
-multiple fontDir directories. If a PDF file uses a font but doesn't
-embed it, these directories will be searched for a matching font file.
-These fonts are used by both xpdf (for display) and pdftops (for
-embedding in the generated PostScript). Type 1 fonts must have a
-suffix of ".pfa", ".pfb", ".ps", or no suffix at all. TrueType fonts
-must have a ".ttf" suffix. Other files in these directories will be
-ignored. There are no default fontDir directories.
+.BR psEmbedType1Fonts " yes | no"
+If set to "no", prevents embedding of Type 1 fonts in generated
+PostScript. This defaults to "yes".
+.TP
+.BR psEmbedTrueTypeFonts " yes | no"
+If set to "no", prevents embedding of TrueType fonts in generated
+PostScript. This defaults to "yes".
+.TP
+.BR psEmbedCIDTrueTypeFonts " yes | no"
+If set to "no", prevents embedding of CID TrueType fonts in generated
+PostScript. For Level 3 PostScript, this generates a CID font, for
+lower levels it generates a non-CID composite font. This defaults to
+"yes".
+.TP
+.BR psEmbedCIDPostScriptFonts " yes | no"
+If set to "no", prevents embedding of CID PostScript fonts in
+generated PostScript. For Level 3 PostScript, this generates a CID
+font, for lower levels it generates a non-CID composite font. This
+defaults to "yes".
.SH POSTSCRIPT CONTROL
.TP
.BI psPaperSize " width(pts) height(pts)"
@@ -243,65 +283,6 @@ duplexing. This defaults to "no".
.BR psLevel " level1 | level1sep | level2 | level2sep | level3 | level3Sep"
Sets the PostScript level to generate. This defaults to "level2".
.TP
-.BI psFont " PDF\-font\-name PS\-font\-name"
-When the
-.I PDF\-font\-name
-font is used in a PDF file, it will be translated to the PostScript
-font
-.IR PS\-font\-name ,
-which is assumed to be resident in the printer. Typically,
-.I PDF\-font\-name
-and
-.I PS\-font\-name
-are the same. By default, only the Base-14 fonts are assumed to be
-resident.
-.TP
-.BI psNamedFont16 " PDF\-font\-name wMode PS\-font\-name encoding"
-When the 16-bit font
-.I PDF\-font\-name
-is used in a PDF file with the
-.I wMode
-writing mode and is not embedded, the
-.I PS\-font\-name
-font is substituted for it. The writing mode must be either \'H' for
-horizontal or \'V' for vertical. The
-.I PS\-font\-name
-font is assumed to be resident in the printer and to use the specified
-encoding (which must have been defined with the unicodeMap command).
-.TP
-.BI psFont16 " registry\-ordering wMode PS\-font\-name encoding"
-When a 16-bit font using the
-.I registry\-ordering
-character collection and
-.I wMode
-writing mode is not embedded and does not match any of the fonts
-declared in psNamedFont16 commands, the
-.I PS\-font\-name
-font is substituted for it. The writing mode must be either \'H' for
-horizontal or \'V' for vertical. The
-.I PS\-font\-name
-font is assumed to be resident in the printer and to use the specified
-writing mode and encoding (which must have been defined with the
-unicodeMap command).
-.TP
-.BR psEmbedType1Fonts " yes | no"
-If set to "no", prevents embedding of Type 1 fonts in generated
-PostScript. This defaults to "yes".
-.TP
-.BR psEmbedTrueTypeFonts " yes | no"
-If set to "no", prevents embedding of TrueType fonts in generated
-PostScript. This defaults to "yes".
-.TP
-.BR psEmbedCIDTrueTypeFonts " yes | no"
-If set to "no", prevents embedding of CID TrueType fonts in generated
-PostScript. For Level 3 PostScript, this generates a CID font, for
-lower levels it generates a non-CID composite font.
-.TP
-.BR psEmbedCIDPostScriptFonts " yes | no"
-If set to "no", prevents embedding of CID PostScript fonts in
-generated PostScript. For Level 3 PostScript, this generates a CID
-font, for lower levels it generates a non-CID composite font.
-.TP
.BR psPreload " yes | no"
If set to "yes", PDF forms are converted to PS procedures, and image
data is preloaded. This uses more memory in the PostScript
@@ -318,6 +299,25 @@ the Xpdf tools were compiled with OPI support. This defaults to "no".
If set to "yes", the ASCIIHexEncode filter will be used instead of
ASCII85Encode for binary data. This defaults to "no".
.TP
+.BR psUncompressPreloadedImages " yes | no"
+If set to "yes", all preloaded images in PS files will uncompressed.
+If set to "no", the original compressed images will be used when
+possible. The "yes" setting is useful to work around certain buggy
+PostScript interpreters. This defaults to "no".
+.TP
+.BR psRasterResolution " float"
+Set the resolution (in dpi) for rasterized pages in PostScript output.
+(Pdftops will rasterize pages which use transparency.) This defaults
+to 300.
+.TP
+.BR psRasterMono " yes | no"
+If set to "yes", rasterized pages in PS files will be monochrome
+(8-bit gray) instead of color. This defaults to "no".
+.TP
+.BR psAlwaysRasterize " yes | no"
+If set to "yes", all PostScript output will be rasterized. This
+defaults to "no".
+.TP
.BI psFile " file\-or\-command"
Sets the default PostScript file or print command for xpdf. Commands
start with a \'|' character; anything else is a file. If the file
@@ -331,7 +331,7 @@ See the description above, in the DISPLAY FONTS section.
.TP
.BI textEncoding " encoding\-name"
Sets the encoding to use for text output. (This can be overridden
-with the "-enc" switch on the command line.) The
+with the "\-enc" switch on the command line.) The
.I encoding\-name
must be defined with the unicodeMap command (see above). This
defaults to "Latin1".
@@ -346,7 +346,7 @@ are:
mac = CR
.fi
-(This can be overridden with the "-eol" switch on the command line.)
+(This can be overridden with the "\-eol" switch on the command line.)
The default value is based on the OS where xpdf and pdftotext were
built.
.TP
@@ -385,6 +385,16 @@ rasterizer). This is only relevant if the Xpdf tools were built with
FreeType support. ("enableFreeType" replaces the old
"freetypeControl" option.) This option defaults to "yes".
.TP
+.BR enableFreeType " yes | no"
+Enables or disables use of FreeType (a TrueType / Type 1 font
+rasterizer). This is only relevant if the Xpdf tools were built with
+FreeType support. ("enableFreeType" replaces the old
+"freetypeControl" option.) This option defaults to "yes".
+.TP
+.BR disableFreeTypeHinting " yes | no"
+If this is set to "yes", FreeType hinting will be forced off. This
+option defaults to "no".
+.TP
.BR antialias " yes | no"
Enables or disables font anti-aliasing in the PDF rasterizer. This
option affects all font rasterizers. ("antialias" replaces the
@@ -395,8 +405,17 @@ anti-aliasing control provided by the old "t1libControl" and
Enables or disables anti-aliasing of vector graphics in the PDF
rasterizer. This defaults to "yes".
.TP
+.BR antialiasPrinting " yes | no"
+If this is "yes", bitmaps sent to the printer will be antialiased
+(according to the "antialias" and "vectorAntialias" settings). If
+this is "no", printed bitmaps will not be antialiased. This defaults
+to "no".
+.TP
.BR strokeAdjust " yes | no"
-Enables or disables stroke adjustment. This defaults to "yes".
+Enables or disables stroke adjustment. Stroke adjustment moves
+horizontal and vertical lines by up to half a pixel to make them look
+"cleaner" when vector anti-aliasing is enabled. This defaults to
+"yes".
.TP
.BR screenType " dispersed | clustered | stochasticClustered"
Sets the halftone screen type, which will be used when generating a
@@ -432,6 +451,30 @@ When halftoning, all values above this threshold are forced to solid
white. This parameter is a floating point value between 0 (black) and
1 (white). The default value is 1.
.TP
+.BI minLineWidth " float"
+Set the minimum line width, in device pixels. This affects the
+rasterizer only, not the PostScript converter (except when it uses
+rasterization to handle transparency). The default value is 0 (no
+minimum).
+.TP
+.BI drawAnnotations " yes | no"
+If set to "no", annotations will not be drawn or printed. The default
+value is "yes".
+.TP
+.BI overprintPreview " yes | no"
+If set to "yes", generate overprint preview output, honoring the
+OP/op/OPM settings in the PDF file. Ignored for non-CMYK output. The
+default value is "no".
+.TP
+.BI launchCommand " command"
+Sets the command executed when you click on a "launch"-type link. The
+intent is for the command to be a program/script which determines the
+file type and runs the appropriate viewer. The command line will
+consist of the file to be launched, followed by any parameters
+specified with the link. Do not use "%s" in "command". By default,
+this is unset, and Xpdf will simply try to execute the file (after
+prompting the user).
+.TP
.BI urlCommand " command"
Sets the command executed when you click on a URL link. The string
"%s" will be replaced with the URL. (See the example below.) This
@@ -451,8 +494,9 @@ there is no way for Xpdf to tell. This defaults to "yes".
.BI mapUnknownCharNames " yes | no"
If set to "yes", and mapNumericCharNames is set to "no", the Xpdf
tools will apply a simple pass-through mapping (Unicode index =
-character code) for all unrecognized glyph names. In some cases, this
-leads to usable text, and in other cases it leads to gibberish --
+character code) for all unrecognized glyph names. (For CID fonts,
+setting mapNumericCharNames to "no" is unnecessary.) In some cases,
+this leads to usable text, and in other cases it leads to gibberish --
there is no way for Xpdf to tell. This defaults to "no".
.TP
.BI bind " modifiers-key context command ..."
@@ -552,20 +596,20 @@ unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap
cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1
# use the Base-14 Type 1 fonts from ghostscript
-displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
-displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
-displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
-displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
-displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
-displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
-displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
-displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
-displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
-displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
-displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
-displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
-displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
-displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
# use the Bakoma Type 1 fonts
# (this assumes they happen to be installed in /usr/local/fonts/bakoma)
@@ -577,21 +621,22 @@ psDuplex no
psLevel level2
psEmbedType1Fonts yes
psEmbedTrueTypeFonts yes
-psFile "| lpr -Pprinter5"
+psFile "| lpr \-Pprinter5"
# assume that the PostScript printer has the Univers and
# Univers-Bold fonts
-psFont Univers Univers
-psFont Univers-Bold Univers-Bold
+psResidentFont Univers Univers
+psResidentFont Univers-Bold Univers-Bold
# set the text output options
textEncoding UTF-8
textEOL unix
# misc options
-t1libControl low
-freetypeControl low
-urlCommand "netscape -remote 'openURL(%s)'"
+enableT1lib yes
+enableFreeType yes
+launchCommand viewer-script
+urlCommand "netscape \-remote 'openURL(%s)'"
.fi
.SH FILES
@@ -604,13 +649,15 @@ Depending on build options, it may be placed elsewhere.
This is the user's configuration file. If it exists, it will be read
in place of the system-wide file.
.SH AUTHOR
-The Xpdf software and documentation are copyright 1996-2007 Glyph &
+The Xpdf software and documentation are copyright 1996-2011 Glyph &
Cog, LLC.
.SH "SEE ALSO"
.BR xpdf (1),
.BR pdftops (1),
.BR pdftotext (1),
.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfdetach (1),
.BR pdftoppm (1),
.BR pdfimages (1)
.br
diff --git a/doc/xpdfrc.cat b/doc/xpdfrc.cat
index 3201f09..db42866 100644
--- a/doc/xpdfrc.cat
+++ b/doc/xpdfrc.cat
@@ -1,472 +1,465 @@
-xpdfrc(5) xpdfrc(5)
+xpdfrc(5) xpdfrc(5)
NAME
- xpdfrc - configuration file for Xpdf tools (version 3.02)
+ xpdfrc - configuration file for Xpdf tools (version 3.03)
DESCRIPTION
- All of the Xpdf tools read a single configuration file.
- If you have a .xpdfrc file in your home directory, it will
- be read. Otherwise, a system-wide configuration file will
- be read from /usr/local/etc/xpdfrc, if it exists. (This
- is its default location; depending on build options, it
- may be placed elsewhere.) On Win32 systems, the xpdfrc
- file should be placed in the same directory as the exe-
- cutables.
-
- The xpdfrc file consists of a series of configuration
- options, one per line. Blank lines and lines starting
- with a '#' (comments) are ignored.
-
- The following sections list all of the configuration
- options, sorted into functional groups. There is an exam-
- ples section at the end.
+ All of the Xpdf tools read a single configuration file. If you have a
+ .xpdfrc file in your home directory, it will be read. Otherwise, a
+ system-wide configuration file will be read from /usr/local/etc/xpdfrc,
+ if it exists. (This is its default location; depending on build
+ options, it may be placed elsewhere.) On Win32 systems, the xpdfrc
+ file should be placed in the same directory as the executables.
+
+ The xpdfrc file consists of a series of configuration options, one per
+ line. Blank lines and lines starting with a '#' (comments) are
+ ignored.
+
+ The following sections list all of the configuration options, sorted
+ into functional groups. There is an examples section at the end.
INCLUDE FILES
include config-file
- Includes the specified config file. The effect of
- this is equivalent to inserting the contents of
- config-file directly into the parent config file in
- place of the include command. Config files can be
- nested arbitrarily deeply.
+ Includes the specified config file. The effect of this is
+ equivalent to inserting the contents of config-file directly
+ into the parent config file in place of the include command.
+ Config files can be nested arbitrarily deeply.
CHARACTER MAPPING
nameToUnicode map-file
- Specifies a file with the mapping from character
- names to Unicode. This is used to handle PDF fonts
- that have valid encodings but no ToUnicode entry.
- Each line of a nameToUnicode file looks like this:
+ Specifies a file with the mapping from character names to Uni-
+ code. This is used to handle PDF fonts that have valid encod-
+ ings but no ToUnicode entry. Each line of a nameToUnicode file
+ looks like this:
hex-string name
- The hex-string is the Unicode (UCS-2) character
- index, and name is the corresponding character
- name. Multiple nameToUnicode files can be used; if
- a character name is given more than once, the code
- in the last specified file is used. There is a
- built-in default nameToUnicode table with all of
- Adobe's standard character names.
+ The hex-string is the Unicode (UCS-2) character index, and name
+ is the corresponding character name. Multiple nameToUnicode
+ files can be used; if a character name is given more than once,
+ the code in the last specified file is used. There is a built-
+ in default nameToUnicode table with all of Adobe's standard
+ character names.
cidToUnicode registry-ordering map-file
- Specifies the file with the mapping from character
- collection to Unicode. Each line of a cidToUnicode
- file represents one character:
+ Specifies the file with the mapping from character collection to
+ Unicode. Each line of a cidToUnicode file represents one char-
+ acter:
hex-string
- The hex-string is the Unicode (UCS-2) index for
- that character. The first line maps CID 0, the
- second line CID 1, etc. File size is determined by
- size of the character collection. Only one file is
- allowed per character collection; the last speci-
- fied file is used. There are no built-in cidToUni-
- code mappings.
+ The hex-string is the Unicode (UCS-2) index for that character.
+ The first line maps CID 0, the second line CID 1, etc. File
+ size is determined by size of the character collection. Only
+ one file is allowed per character collection; the last specified
+ file is used. There are no built-in cidToUnicode mappings.
unicodeToUnicode font-name-substring map-file
- This is used to work around PDF fonts which have
- incorrect Unicode information. It specifies a file
- which maps from the given (incorrect) Unicode
- indexes to the correct ones. The mapping will be
- used for any font whose name contains
- font-name-substring. Each line of a unicodeToUni-
- code file represents one Unicode character:
+ This is used to work around PDF fonts which have incorrect Uni-
+ code information. It specifies a file which maps from the given
+ (incorrect) Unicode indexes to the correct ones. The mapping
+ will be used for any font whose name contains font-name-sub-
+ string. Each line of a unicodeToUnicode file represents one
+ Unicode character:
in-hex out-hex1 out-hex2 ...
- The in-hex field is an input (incorrect) Unicode
- index, and the rest of the fields are one or more
- output (correct) Unicode indexes. Each occurrence
- of in-hex will be converted to the specified output
- sequence.
+ The in-hex field is an input (incorrect) Unicode index, and the
+ rest of the fields are one or more output (correct) Unicode
+ indexes. Each occurrence of in-hex will be converted to the
+ specified output sequence.
unicodeMap encoding-name map-file
- Specifies the file with mapping from Unicode to
- encoding-name. These encodings are used for X dis-
- play fonts and text output (see below). Each line
- of a unicodeMap file represents a range of one or
- more Unicode characters which maps linearly to a
- range in the output encoding:
+ Specifies the file with mapping from Unicode to encoding-name.
+ These encodings are used for text output (see below). Each line
+ of a unicodeMap file represents a range of one or more Unicode
+ characters which maps linearly to a range in the output encod-
+ ing:
in-start-hex in-end-hex out-start-hex
- Entries for single characters can be abbreviated
- to:
+ Entries for single characters can be abbreviated to:
in-hex out-hex
- The in-start-hex and in-end-hex fields (or the sin-
- gle in-hex field) specify the Unicode range. The
- out-start-hex field (or the out-hex field) speci-
- fies the start of the output encoding range. The
- length of the out-start-hex (or out-hex) string
- determines the length of the output characters
- (e.g., UTF-8 uses different numbers of bytes to
- represent characters in different ranges). Entries
- must be given in increasing Unicode order. Only
- one file is allowed per encoding; the last speci-
- fied file is used. The Latin1, ASCII7, Symbol,
- ZapfDingbats, UTF-8, and UCS-2 encodings are prede-
- fined.
+ The in-start-hex and in-end-hex fields (or the single in-hex
+ field) specify the Unicode range. The out-start-hex field (or
+ the out-hex field) specifies the start of the output encoding
+ range. The length of the out-start-hex (or out-hex) string
+ determines the length of the output characters (e.g., UTF-8 uses
+ different numbers of bytes to represent characters in different
+ ranges). Entries must be given in increasing Unicode order.
+ Only one file is allowed per encoding; the last specified file
+ is used. The Latin1, ASCII7, Symbol, ZapfDingbats, UTF-8, and
+ UCS-2 encodings are predefined.
cMapDir registry-ordering dir
- Specifies a search directory, dir, for CMaps for
- the registry-ordering character collection. There
- can be multiple directories for a particular col-
- lection. There are no default CMap directories.
+ Specifies a search directory, dir, for CMaps for the reg-
+ istry-ordering character collection. There can be multiple
+ directories for a particular collection. There are no default
+ CMap directories.
toUnicodeDir dir
- Specifies a search directory, dir, for ToUnicode
- CMaps. There can be multiple ToUnicode directo-
- ries. There are no default ToUnicode directories.
-
-DISPLAY FONTS
- displayFontT1 PDF-font-name T1-file
- Maps a PDF font, PDF-font-name, to a Type 1 font
- for display. The Type 1 font file, T1-file, should
- be a standard .pfa or .pfb file.
-
- displayFontTT PDF-font-name TT-file
- Maps a PDF font, PDF-font-name, to a TrueType font
- for display. The TrueType font file, TT-file,
- should be a standard .ttf file.
-
- displayNamedCIDFontT1 PDF-font-name T1-file
- Maps a specific PDF CID (16-bit) font,
- PDF-font-name, to a CID font (16-bit PostScript
- font), for display. There are no default CID font
- mappings.
-
- displayCIDFontT1 registry-ordering T1-file
- Maps the registry-ordering character collection to
- a CID font (16-bit PostScript font), for display.
- This mapping is used if the font name doesn't match
- any of the fonts declared with displayNamedCIDFont*
- commands. There are no default CID font mappings.
-
- displayNamedCIDFontTT PDF-font-name TT-file
- Maps a specific PDF CID (16-bit) font,
- PDF-font-name, to a (16-bit) TrueType font, for
- display. There are no default CID font mappings.
-
- displayCIDFontTT registry-ordering TT-file
- Maps the registry-ordering character collection to
- a (16-bit) TrueType font, for display. This map-
- ping is used if the font name doesn't match any of
- the fonts declared with displayNamedCIDFont* com-
- mands. There are no default CID font mappings.
+ Specifies a search directory, dir, for ToUnicode CMaps. There
+ can be multiple ToUnicode directories. There are no default
+ ToUnicode directories.
+
+GENERAL FONT CONFIGURATION
+ fontFile PDF-font-name font-file
+ Maps a PDF font, PDF-font-name, to a font for display or Post-
+ Script output. The font file, font-file, can be any type
+ allowed in a PDF file. This command can be used for 8-bit or
+ 16-bit (CID) fonts.
fontDir dir
- Specifies a search directory for external font
- files. There can be multiple fontDir directories.
- If a PDF file uses a font but doesn't embed it,
- these directories will be searched for a matching
- font file. These fonts are used by both xpdf (for
- display) and pdftops (for embedding in the gener-
- ated PostScript). Type 1 fonts must have a suffix
- of ".pfa", ".pfb", ".ps", or no suffix at all.
- TrueType fonts must have a ".ttf" suffix. Other
- files in these directories will be ignored. There
- are no default fontDir directories.
+ Specifies a search directory for font files. There can be mul-
+ tiple fontDir commands; all of the specified directories will be
+ searched in order. The font files can be Type 1 (.pfa or .pfb)
+ or TrueType (.ttf or .ttc); other files in the directory will be
+ ignored. The font file name (not including the extension) must
+ exactly match the PDF font name. This search is performed if
+ the font name doesn't match any of the fonts declared with the
+ fontFile command. There are no default fontDir directories.
+
+ fontFileCC registry-ordering font-file
+ Maps the registry-ordering character collection to a font for
+ display or PostScript output. This mapping is used if the font
+ name doesn't match any of the fonts declared with the fontFile,
+ fontDir, psResidentFont16, or psResidentFontCC commands.
+
+POSTSCRIPT FONT CONFIGURATION
+ psFontPassthrough yes | no
+ If set to "yes", pass 8-bit font names through to the PostScript
+ output without substitution. Fonts which are not embedded in
+ the PDF file are expected to be available on the printer. This
+ defaults to "no".
+
+ psResidentFont PDF-font-name PS-font-name
+ When the 8-bit font PDF-font-name is used (without embedding) in
+ a PDF file, it will be translated to the PostScript font
+ PS-font-name, which is assumed to be resident in the printer.
+ Typically, PDF-font-name and PS-font-name are the same. By
+ default, only the Base-14 fonts are assumed to be resident.
+
+ psResidentFont16 PDF-font-name wMode PS-font-name encoding
+ When the 16-bit (CID) font PDF-font-name with writing mode wMode
+ is used (without embedding) in a PDF file, it will be translated
+ to the PostScript font PS-font-name, which is assumbed to be
+ resident in the printer. The writing mode must be either 'H'
+ for horizontal or 'V' for vertical. The resident font is
+ assumed to use the specified encoding (which must have been
+ defined with the unicodeMap command).
+
+ psResidentFontCC registry-ordering wMode PS-font-name encoding
+ When a 16-bit (CID) font using the registry-ordering character
+ collection and wMode writing mode is used (without embedding) in
+ a PDF file, the PostScript font, PS-font-name, is substituted
+ for it. The substituted font is assumbed to be resident in the
+ printer. The writing mode must be either 'H' for horizontal or
+ 'V' for vertical. The resident font is assumed to use the spec-
+ ified encoding (which must have been defined with the unicodeMap
+ command).
+
+ psEmbedType1Fonts yes | no
+ If set to "no", prevents embedding of Type 1 fonts in generated
+ PostScript. This defaults to "yes".
+
+ psEmbedTrueTypeFonts yes | no
+ If set to "no", prevents embedding of TrueType fonts in gener-
+ ated PostScript. This defaults to "yes".
+
+ psEmbedCIDTrueTypeFonts yes | no
+ If set to "no", prevents embedding of CID TrueType fonts in gen-
+ erated PostScript. For Level 3 PostScript, this generates a CID
+ font, for lower levels it generates a non-CID composite font.
+ This defaults to "yes".
+
+ psEmbedCIDPostScriptFonts yes | no
+ If set to "no", prevents embedding of CID PostScript fonts in
+ generated PostScript. For Level 3 PostScript, this generates a
+ CID font, for lower levels it generates a non-CID composite
+ font. This defaults to "yes".
POSTSCRIPT CONTROL
psPaperSize width(pts) height(pts)
- Sets the paper size for PostScript output. The
- width and height parameters give the paper size in
- PostScript points (1 point = 1/72 inch).
+ Sets the paper size for PostScript output. The width and height
+ parameters give the paper size in PostScript points (1 point =
+ 1/72 inch).
psPaperSize letter | legal | A4 | A3 | match
- Sets the paper size for PostScript output to a
- standard size. The default paper size is set when
- xpdf and pdftops are built, typically to "letter"
- or "A4". This can also be set to "match", which
- will set the paper size to match the size specified
- in the PDF file.
+ Sets the paper size for PostScript output to a standard size.
+ The default paper size is set when xpdf and pdftops are built,
+ typically to "letter" or "A4". This can also be set to "match",
+ which will set the paper size to match the size specified in the
+ PDF file.
psImageableArea llx lly urx ury
- Sets the imageable area for PostScript output. The
- four integers are the coordinates of the lower-left
- and upper-right corners of the imageable region,
- specified in points (with the origin being the
- lower-left corner of the paper). This defaults to
- the full paper size; the psPaperSize option will
- reset the imageable area coordinates.
+ Sets the imageable area for PostScript output. The four inte-
+ gers are the coordinates of the lower-left and upper-right cor-
+ ners of the imageable region, specified in points (with the ori-
+ gin being the lower-left corner of the paper). This defaults to
+ the full paper size; the psPaperSize option will reset the
+ imageable area coordinates.
psCrop yes | no
- If set to "yes", PostScript output is cropped to
- the CropBox specified in the PDF file; otherwise no
- cropping is done. This defaults to "yes".
+ If set to "yes", PostScript output is cropped to the CropBox
+ specified in the PDF file; otherwise no cropping is done. This
+ defaults to "yes".
psExpandSmaller yes | no
- If set to "yes", PDF pages smaller than the
- PostScript imageable area are expanded to fill the
- imageable area. Otherwise, no scalling is done on
- smaller pages. This defaults to "no".
+ If set to "yes", PDF pages smaller than the PostScript imageable
+ area are expanded to fill the imageable area. Otherwise, no
+ scalling is done on smaller pages. This defaults to "no".
psShrinkLarger yes | no
- If set to yes, PDF pages larger than the PostScript
- imageable area are shrunk to fit the imageable
- area. Otherwise, no scaling is done on larger
- pages. This defaults to "yes".
+ If set to yes, PDF pages larger than the PostScript imageable
+ area are shrunk to fit the imageable area. Otherwise, no scal-
+ ing is done on larger pages. This defaults to "yes".
psCenter yes | no
- If set to yes, PDF pages smaller than the
- PostScript imageable area (after any scaling) are
- centered in the imageable area. Otherwise, they
- are aligned at the lower-left corner of the image-
- able area. This defaults to "yes".
+ If set to yes, PDF pages smaller than the PostScript imageable
+ area (after any scaling) are centered in the imageable area.
+ Otherwise, they are aligned at the lower-left corner of the
+ imageable area. This defaults to "yes".
psDuplex yes | no
- If set to "yes", the generated PostScript will set
- the "Duplex" pagedevice entry. This tells duplex-
- capable printers to enable duplexing. This
- defaults to "no".
-
- psLevel level1 | level1sep | level2 | level2sep | level3 |
- level3Sep
- Sets the PostScript level to generate. This
- defaults to "level2".
-
- psFont PDF-font-name PS-font-name
- When the PDF-font-name font is used in a PDF file,
- it will be translated to the PostScript font
- PS-font-name, which is assumed to be resident in
- the printer. Typically, PDF-font-name and
- PS-font-name are the same. By default, only the
- Base-14 fonts are assumed to be resident.
-
- psNamedFont16 PDF-font-name wMode PS-font-name encoding
- When the 16-bit font PDF-font-name is used in a PDF
- file with the wMode writing mode and is not embed-
- ded, the PS-font-name font is substituted for it.
- The writing mode must be either 'H' for horizontal
- or 'V' for vertical. The PS-font-name font is
- assumed to be resident in the printer and to use
- the specified encoding (which must have been
- defined with the unicodeMap command).
-
- psFont16 registry-ordering wMode PS-font-name encoding
- When a 16-bit font using the registry-ordering
- character collection and wMode writing mode is not
- embedded and does not match any of the fonts
- declared in psNamedFont16 commands, the
- PS-font-name font is substituted for it. The writ-
- ing mode must be either 'H' for horizontal or 'V'
- for vertical. The PS-font-name font is assumed to
- be resident in the printer and to use the specified
- writing mode and encoding (which must have been
- defined with the unicodeMap command).
+ If set to "yes", the generated PostScript will set the "Duplex"
+ pagedevice entry. This tells duplex-capable printers to enable
+ duplexing. This defaults to "no".
- psEmbedType1Fonts yes | no
- If set to "no", prevents embedding of Type 1 fonts
- in generated PostScript. This defaults to "yes".
-
- psEmbedTrueTypeFonts yes | no
- If set to "no", prevents embedding of TrueType
- fonts in generated PostScript. This defaults to
- "yes".
-
- psEmbedCIDTrueTypeFonts yes | no
- If set to "no", prevents embedding of CID TrueType
- fonts in generated PostScript. For Level 3
- PostScript, this generates a CID font, for lower
- levels it generates a non-CID composite font.
-
- psEmbedCIDPostScriptFonts yes | no
- If set to "no", prevents embedding of CID
- PostScript fonts in generated PostScript. For
- Level 3 PostScript, this generates a CID font, for
- lower levels it generates a non-CID composite font.
+ psLevel level1 | level1sep | level2 | level2sep | level3 | level3Sep
+ Sets the PostScript level to generate. This defaults to
+ "level2".
psPreload yes | no
- If set to "yes", PDF forms are converted to PS pro-
- cedures, and image data is preloaded. This uses
- more memory in the PostScript interpreter, but gen-
- erates significantly smaller PS files in situations
- where, e.g., the same image is drawn on every page
+ If set to "yes", PDF forms are converted to PS procedures, and
+ image data is preloaded. This uses more memory in the Post-
+ Script interpreter, but generates significantly smaller PS files
+ in situations where, e.g., the same image is drawn on every page
of a long document. This defaults to "no".
psOPI yes | no
- If set to "yes", generates PostScript OPI comments
- for all images and forms which have OPI informa-
- tion. This option is only available if the Xpdf
- tools were compiled with OPI support. This
- defaults to "no".
+ If set to "yes", generates PostScript OPI comments for all
+ images and forms which have OPI information. This option is
+ only available if the Xpdf tools were compiled with OPI support.
+ This defaults to "no".
psASCIIHex yes | no
- If set to "yes", the ASCIIHexEncode filter will be
- used instead of ASCII85Encode for binary data.
- This defaults to "no".
+ If set to "yes", the ASCIIHexEncode filter will be used instead
+ of ASCII85Encode for binary data. This defaults to "no".
+
+ psUncompressPreloadedImages yes | no
+ If set to "yes", all preloaded images in PS files will uncom-
+ pressed. If set to "no", the original compressed images will be
+ used when possible. The "yes" setting is useful to work around
+ certain buggy PostScript interpreters. This defaults to "no".
+
+ psRasterResolution float
+ Set the resolution (in dpi) for rasterized pages in PostScript
+ output. (Pdftops will rasterize pages which use transparency.)
+ This defaults to 300.
+
+ psRasterMono yes | no
+ If set to "yes", rasterized pages in PS files will be monochrome
+ (8-bit gray) instead of color. This defaults to "no".
+
+ psAlwaysRasterize yes | no
+ If set to "yes", all PostScript output will be rasterized. This
+ defaults to "no".
psFile file-or-command
- Sets the default PostScript file or print command
- for xpdf. Commands start with a '|' character;
- anything else is a file. If the file name or com-
- mand contains spaces it must be quoted. This
- defaults to unset, which tells xpdf to generate a
- name of the form <file>.ps for a PDF file
- <file>.pdf.
+ Sets the default PostScript file or print command for xpdf.
+ Commands start with a '|' character; anything else is a file.
+ If the file name or command contains spaces it must be quoted.
+ This defaults to unset, which tells xpdf to generate a name of
+ the form <file>.ps for a PDF file <file>.pdf.
fontDir dir
- See the description above, in the DISPLAY FONTS
- section.
+ See the description above, in the DISPLAY FONTS section.
TEXT CONTROL
textEncoding encoding-name
- Sets the encoding to use for text output. (This
- can be overridden with the "-enc" switch on the
- command line.) The encoding-name must be defined
- with the unicodeMap command (see above). This
- defaults to "Latin1".
+ Sets the encoding to use for text output. (This can be overrid-
+ den with the "-enc" switch on the command line.) The encod-
+ ing-name must be defined with the unicodeMap command (see
+ above). This defaults to "Latin1".
textEOL unix | dos | mac
- Sets the end-of-line convention to use for text
- output. The options are:
+ Sets the end-of-line convention to use for text output. The
+ options are:
unix = LF
dos = CR+LF
mac = CR
- (This can be overridden with the "-eol" switch on
- the command line.) The default value is based on
- the OS where xpdf and pdftotext were built.
+ (This can be overridden with the "-eol" switch on the command
+ line.) The default value is based on the OS where xpdf and
+ pdftotext were built.
textPageBreaks yes | no
- If set to "yes", text extraction will insert page
- breaks (form feed characters) between pages. This
- defaults to "yes".
+ If set to "yes", text extraction will insert page breaks (form
+ feed characters) between pages. This defaults to "yes".
textKeepTinyChars yes | no
- If set to "yes", text extraction will keep all
- characters. If set to "no", text extraction will
- discard tiny (smaller than 3 point) characters
- after the first 50000 per page, avoiding extremely
- slow run times for PDF files that use special fonts
- to do shading or cross-hatching. This defaults to
- "no".
+ If set to "yes", text extraction will keep all characters. If
+ set to "no", text extraction will discard tiny (smaller than 3
+ point) characters after the first 50000 per page, avoiding
+ extremely slow run times for PDF files that use special fonts to
+ do shading or cross-hatching. This defaults to "no".
MISCELLANEOUS SETTINGS
initialZoom percentage | page | width
- Sets the initial zoom factor. A number specifies a
- zoom percentage, where 100 means 72 dpi. You may
- also specify 'page', to fit the page to the window
- size, or 'width', to fit the page width to the win-
- dow width.
+ Sets the initial zoom factor. A number specifies a zoom per-
+ centage, where 100 means 72 dpi. You may also specify 'page',
+ to fit the page to the window size, or 'width', to fit the page
+ width to the window width.
continuousView yes | no
- If set to "yes", xpdf will start in continuous view
- mode, i.e., with one vertical screoll bar for the
- whole document. This defaults to "no".
+ If set to "yes", xpdf will start in continuous view mode, i.e.,
+ with one vertical screoll bar for the whole document. This
+ defaults to "no".
enableT1lib yes | no
- Enables or disables use of t1lib (a Type 1 font
- rasterizer). This is only relevant if the Xpdf
- tools were built with t1lib support.
- ("enableT1lib" replaces the old "t1libControl"
+ Enables or disables use of t1lib (a Type 1 font rasterizer).
+ This is only relevant if the Xpdf tools were built with t1lib
+ support. ("enableT1lib" replaces the old "t1libControl"
option.) This option defaults to "yes".
enableFreeType yes | no
- Enables or disables use of FreeType (a TrueType /
- Type 1 font rasterizer). This is only relevant if
- the Xpdf tools were built with FreeType support.
- ("enableFreeType" replaces the old "freetypeCon-
- trol" option.) This option defaults to "yes".
+ Enables or disables use of FreeType (a TrueType / Type 1 font
+ rasterizer). This is only relevant if the Xpdf tools were built
+ with FreeType support. ("enableFreeType" replaces the old
+ "freetypeControl" option.) This option defaults to "yes".
+
+ enableFreeType yes | no
+ Enables or disables use of FreeType (a TrueType / Type 1 font
+ rasterizer). This is only relevant if the Xpdf tools were built
+ with FreeType support. ("enableFreeType" replaces the old
+ "freetypeControl" option.) This option defaults to "yes".
+
+ disableFreeTypeHinting yes | no
+ If this is set to "yes", FreeType hinting will be forced off.
+ This option defaults to "no".
antialias yes | no
- Enables or disables font anti-aliasing in the PDF
- rasterizer. This option affects all font rasteriz-
- ers. ("antialias" replaces the anti-aliasing con-
- trol provided by the old "t1libControl" and
+ Enables or disables font anti-aliasing in the PDF rasterizer.
+ This option affects all font rasterizers. ("antialias" replaces
+ the anti-aliasing control provided by the old "t1libControl" and
"freetypeControl" options.) This default to "yes".
vectorAntialias yes | no
- Enables or disables anti-aliasing of vector graph-
- ics in the PDF rasterizer. This defaults to "yes".
+ Enables or disables anti-aliasing of vector graphics in the PDF
+ rasterizer. This defaults to "yes".
+
+ antialiasPrinting yes | no
+ If this is "yes", bitmaps sent to the printer will be
+ antialiased (according to the "antialias" and "vectorAntialias"
+ settings). If this is "no", printed bitmaps will not be
+ antialiased. This defaults to "no".
strokeAdjust yes | no
- Enables or disables stroke adjustment. This
+ Enables or disables stroke adjustment. Stroke adjustment moves
+ horizontal and vertical lines by up to half a pixel to make them
+ look "cleaner" when vector anti-aliasing is enabled. This
defaults to "yes".
screenType dispersed | clustered | stochasticClustered
- Sets the halftone screen type, which will be used
- when generating a monochrome (1-bit) bitmap. The
- three options are dispersed-dot dithering, clus-
- tered-dot dithering (with a round dot and 45-degree
- screen angle), and stochastic clustered-dot dither-
- ing. By default, "stochasticClustered" is used for
- resolutions of 300 dpi and higher, and "dispersed"
- is used for resolutions lower then 300 dpi.
+ Sets the halftone screen type, which will be used when generat-
+ ing a monochrome (1-bit) bitmap. The three options are dis-
+ persed-dot dithering, clustered-dot dithering (with a round dot
+ and 45-degree screen angle), and stochastic clustered-dot
+ dithering. By default, "stochasticClustered" is used for reso-
+ lutions of 300 dpi and higher, and "dispersed" is used for reso-
+ lutions lower then 300 dpi.
screenSize integer
- Sets the size of the (square) halftone screen
- threshold matrix. By default, this is 4 for dis-
- persed-dot dithering, 10 for clustered-dot dither-
- ing, and 100 for stochastic clustered-dot dither-
- ing.
+ Sets the size of the (square) halftone screen threshold matrix.
+ By default, this is 4 for dispersed-dot dithering, 10 for clus-
+ tered-dot dithering, and 100 for stochastic clustered-dot
+ dithering.
screenDotRadius integer
- Sets the halftone screen dot radius. This is only
- used when screenType is set to stochasticClustered,
- and it defaults to 2. In clustered-dot mode, the
- dot radius is half of the screen size. Dispersed-
- dot dithering doesn't have a dot radius.
+ Sets the halftone screen dot radius. This is only used when
+ screenType is set to stochasticClustered, and it defaults to 2.
+ In clustered-dot mode, the dot radius is half of the screen
+ size. Dispersed-dot dithering doesn't have a dot radius.
screenGamma float
- Sets the halftone screen gamma correction parame-
- ter. Gamma values greater than 1 make the output
- brighter; gamma values less than 1 make it darker.
- The default value is 1.
+ Sets the halftone screen gamma correction parameter. Gamma val-
+ ues greater than 1 make the output brighter; gamma values less
+ than 1 make it darker. The default value is 1.
screenBlackThreshold float
- When halftoning, all values below this threshold
- are forced to solid black. This parameter is a
- floating point value between 0 (black) and 1
- (white). The default value is 0.
+ When halftoning, all values below this threshold are forced to
+ solid black. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 0.
screenWhiteThreshold float
- When halftoning, all values above this threshold
- are forced to solid white. This parameter is a
- floating point value between 0 (black) and 1
- (white). The default value is 1.
+ When halftoning, all values above this threshold are forced to
+ solid white. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 1.
+
+ minLineWidth float
+ Set the minimum line width, in device pixels. This affects the
+ rasterizer only, not the PostScript converter (except when it
+ uses rasterization to handle transparency). The default value
+ is 0 (no minimum).
+
+ drawAnnotations yes | no
+ If set to "no", annotations will not be drawn or printed. The
+ default value is "yes".
+
+ overprintPreview yes | no
+ If set to "yes", generate overprint preview output, honoring the
+ OP/op/OPM settings in the PDF file. Ignored for non-CMYK out-
+ put. The default value is "no".
+
+ launchCommand command
+ Sets the command executed when you click on a "launch"-type
+ link. The intent is for the command to be a program/script
+ which determines the file type and runs the appropriate viewer.
+ The command line will consist of the file to be launched, fol-
+ lowed by any parameters specified with the link. Do not use
+ "%s" in "command". By default, this is unset, and Xpdf will
+ simply try to execute the file (after prompting the user).
urlCommand command
- Sets the command executed when you click on a URL
- link. The string "%s" will be replaced with the
- URL. (See the example below.) This has no default
- value.
+ Sets the command executed when you click on a URL link. The
+ string "%s" will be replaced with the URL. (See the example
+ below.) This has no default value.
movieCommand command
- Sets the command executed when you click on a movie
- annotation. The string "%s" will be replaced with
- the movie file name. This has no default value.
+ Sets the command executed when you click on a movie annotation.
+ The string "%s" will be replaced with the movie file name. This
+ has no default value.
mapNumericCharNames yes | no
- If set to "yes", the Xpdf tools will attempt to map
- various numeric character names sometimes used in
- font subsets. In some cases this leads to usable
- text, and in other cases it leads to gibberish --
- there is no way for Xpdf to tell. This defaults to
+ If set to "yes", the Xpdf tools will attempt to map various
+ numeric character names sometimes used in font subsets. In some
+ cases this leads to usable text, and in other cases it leads to
+ gibberish -- there is no way for Xpdf to tell. This defaults to
"yes".
mapUnknownCharNames yes | no
- If set to "yes", and mapNumericCharNames is set to
- "no", the Xpdf tools will apply a simple pass-
- through mapping (Unicode index = character code)
- for all unrecognized glyph names. In some cases,
- this leads to usable text, and in other cases it
- leads to gibberish -- there is no way for Xpdf to
- tell. This defaults to "no".
+ If set to "yes", and mapNumericCharNames is set to "no", the
+ Xpdf tools will apply a simple pass-through mapping (Unicode
+ index = character code) for all unrecognized glyph names. (For
+ CID fonts, setting mapNumericCharNames to "no" is unnecessary.)
+ In some cases, this leads to usable text, and in other cases it
+ leads to gibberish -- there is no way for Xpdf to tell. This
+ defaults to "no".
bind modifiers-key context command ...
- Add a key or mouse button binding. Modifiers can
- be zero or more of:
+ Add a key or mouse button binding. Modifiers can be zero or
+ more of:
shift-
ctrl-
alt-
- Key can be a regular ASCII character, or any one
- of:
+ Key can be a regular ASCII character, or any one of:
space
tab
@@ -484,25 +477,23 @@ MISCELLANEOUS SETTINGS
mousePress1 .. mousePress7 (mouse buttons)
mouseRelease1 .. mouseRelease7 (mouse buttons)
- Context is either "any" or a comma-separated combi-
- nation of:
+ Context is either "any" or a comma-separated combination of:
fullScreen / window (full screen mode on/off)
continuous / singlePage (continuous mode on/off)
overLink / offLink (mouse over link or not)
scrLockOn / scrLockOff (scroll lock on/off)
- The context string can include only one of each
- pair in the above list.
+ The context string can include only one of each pair in the
+ above list.
- Command is an Xpdf command (see the COMMANDS sec-
- tion of the xpdf(1) man page for details). Multi-
- ple commands are separated by whitespace.
+ Command is an Xpdf command (see the COMMANDS section of the
+ xpdf(1) man page for details). Multiple commands are separated
+ by whitespace.
- The bind command replaces any existing binding, but
- only if it was defined for the exact same modi-
- fiers, key, and context. All tokens (modifiers,
- key, context, commands) are case-sensitive.
+ The bind command replaces any existing binding, but only if it
+ was defined for the exact same modifiers, key, and context. All
+ tokens (modifiers, key, context, commands) are case-sensitive.
Example key bindings:
@@ -518,22 +509,19 @@ MISCELLANEOUS SETTINGS
See the xpdf(1) man page for more examples.
unbind modifiers-key context
- Removes a key binding established with the bind
- command. This is most useful to remove default key
- bindings before establishing new ones (e.g., if the
- default key binding is given for "any" context, and
- you want to create new key bindings for multiple
- contexts).
+ Removes a key binding established with the bind command. This
+ is most useful to remove default key bindings before establish-
+ ing new ones (e.g., if the default key binding is given for
+ "any" context, and you want to create new key bindings for mul-
+ tiple contexts).
printCommands yes | no
- If set to "yes", drawing commands are printed as
- they're executed (useful for debugging). This
- defaults to "no".
+ If set to "yes", drawing commands are printed as they're exe-
+ cuted (useful for debugging). This defaults to "no".
errQuiet yes | no
- If set to "yes", this suppresses all error and
- warning messages from all of the Xpdf tools. This
- defaults to "no".
+ If set to "yes", this suppresses all error and warning messages
+ from all of the Xpdf tools. This defaults to "no".
EXAMPLES
The following is a sample xpdfrc file.
@@ -547,20 +535,20 @@ EXAMPLES
cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1
# use the Base-14 Type 1 fonts from ghostscript
- displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
- displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
- displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
- displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
- displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
- displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
- displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
- displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
- displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
- displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
- displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
- displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
- displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
- displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+ fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+ fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+ fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+ fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+ fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+ fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+ fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+ fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+ fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+ fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+ fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+ fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+ fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+ fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
# use the Bakoma Type 1 fonts
# (this assumes they happen to be installed in /usr/local/fonts/bakoma)
@@ -576,39 +564,38 @@ EXAMPLES
# assume that the PostScript printer has the Univers and
# Univers-Bold fonts
- psFont Univers Univers
- psFont Univers-Bold Univers-Bold
+ psResidentFont Univers Univers
+ psResidentFont Univers-Bold Univers-Bold
# set the text output options
textEncoding UTF-8
textEOL unix
# misc options
- t1libControl low
- freetypeControl low
+ enableT1lib yes
+ enableFreeType yes
+ launchCommand viewer-script
urlCommand "netscape -remote 'openURL(%s)'"
FILES
/usr/local/etc/xpdfrc
- This is the default location for the system-wide
- configuration file. Depending on build options, it
- may be placed elsewhere.
+ This is the default location for the system-wide configuration
+ file. Depending on build options, it may be placed elsewhere.
$HOME/.xpdfrc
- This is the user's configuration file. If it
- exists, it will be read in place of the system-wide
- file.
+ This is the user's configuration file. If it exists, it will be
+ read in place of the system-wide file.
AUTHOR
- The Xpdf software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The Xpdf software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
SEE ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1),
- pdftoppm(1), pdfimages(1)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdfimages(1)
http://www.foolabs.com/xpdf/
- 27 February 2007 xpdfrc(5)
+ 15 August 2011 xpdfrc(5)
diff --git a/doc/xpdfrc.hlp b/doc/xpdfrc.hlp
index deb9fb4..224456c 100644
--- a/doc/xpdfrc.hlp
+++ b/doc/xpdfrc.hlp
@@ -2,466 +2,465 @@
1 xpdfrc
2 NCLUDE_FILE
- xpdfrc - configuration file for Xpdf tools (version 3.02)
+ xpdfrc - configuration file for Xpdf tools (version 3.03)
include config-file
- Includes the specified config file. The effect of
- this is equivalent to inserting the contents of
- config-file directly into the parent config file in
- place of the include command. Config files can be
- nested arbitrarily deeply.
+ Includes the specified config file. The effect of this is
+ equivalent to inserting the contents of config-file directly
+ into the parent config file in place of the include command.
+ Config files can be nested arbitrarily deeply.
- ()
+ ()
2 HARACTER_MAPPIN
nameToUnicode map-file
- Specifies a file with the mapping from character
- names to Unicode. This is used to handle PDF fonts
- that have valid encodings but no ToUnicode entry.
- Each line of a nameToUnicode file looks like this:
+ Specifies a file with the mapping from character names to Uni-
+ code. This is used to handle PDF fonts that have valid encod-
+ ings but no ToUnicode entry. Each line of a nameToUnicode file
+ looks like this:
hex-string name
- The hex-string is the Unicode (UCS-2) character
- index, and name is the corresponding character
- name. Multiple nameToUnicode files can be used; if
- a character name is given more than once, the code
- in the last specified file is used. There is a
- built-in default nameToUnicode table with all of
- Adobe's standard character names.
+ The hex-string is the Unicode (UCS-2) character index, and name
+ is the corresponding character name. Multiple nameToUnicode
+ files can be used; if a character name is given more than once,
+ the code in the last specified file is used. There is a built-
+ in default nameToUnicode table with all of Adobe's standard
+ character names.
cidToUnicode registry-ordering map-file
- Specifies the file with the mapping from character
- collection to Unicode. Each line of a cidToUnicode
- file represents one character:
+ Specifies the file with the mapping from character collection to
+ Unicode. Each line of a cidToUnicode file represents one char-
+ acter:
hex-string
- The hex-string is the Unicode (UCS-2) index for
- that character. The first line maps CID 0, the
- second line CID 1, etc. File size is determined by
- size of the character collection. Only one file is
- allowed per character collection; the last speci-
- fied file is used. There are no built-in cidToUni-
- code mappings.
+ The hex-string is the Unicode (UCS-2) index for that character.
+ The first line maps CID 0, the second line CID 1, etc. File
+ size is determined by size of the character collection. Only
+ one file is allowed per character collection; the last specified
+ file is used. There are no built-in cidToUnicode mappings.
unicodeToUnicode font-name-substring map-file
- This is used to work around PDF fonts which have
- incorrect Unicode information. It specifies a file
- which maps from the given (incorrect) Unicode
- indexes to the correct ones. The mapping will be
- used for any font whose name contains
- font-name-substring. Each line of a unicodeToUni-
- code file represents one Unicode character:
+ This is used to work around PDF fonts which have incorrect Uni-
+ code information. It specifies a file which maps from the given
+ (incorrect) Unicode indexes to the correct ones. The mapping
+ will be used for any font whose name contains font-name-sub-
+ string. Each line of a unicodeToUnicode file represents one
+ Unicode character:
in-hex out-hex1 out-hex2 ...
- The in-hex field is an input (incorrect) Unicode
- index, and the rest of the fields are one or more
- output (correct) Unicode indexes. Each occurrence
- of in-hex will be converted to the specified output
- sequence.
+ The in-hex field is an input (incorrect) Unicode index, and the
+ rest of the fields are one or more output (correct) Unicode
+ indexes. Each occurrence of in-hex will be converted to the
+ specified output sequence.
unicodeMap encoding-name map-file
- Specifies the file with mapping from Unicode to
- encoding-name. These encodings are used for X dis-
- play fonts and text output (see below). Each line
- of a unicodeMap file represents a range of one or
- more Unicode characters which maps linearly to a
- range in the output encoding:
+ Specifies the file with mapping from Unicode to encoding-name.
+ These encodings are used for text output (see below). Each line
+ of a unicodeMap file represents a range of one or more Unicode
+ characters which maps linearly to a range in the output encod-
+ ing:
in-start-hex in-end-hex out-start-hex
- Entries for single characters can be abbreviated
- to:
+ Entries for single characters can be abbreviated to:
in-hex out-hex
- The in-start-hex and in-end-hex fields (or the sin-
- gle in-hex field) specify the Unicode range. The
- out-start-hex field (or the out-hex field) speci-
- fies the start of the output encoding range. The
- length of the out-start-hex (or out-hex) string
- determines the length of the output characters
- (e.g., UTF-8 uses different numbers of bytes to
- represent characters in different ranges). Entries
- must be given in increasing Unicode order. Only
- one file is allowed per encoding; the last speci-
- fied file is used. The Latin1, ASCII7, Symbol,
- ZapfDingbats, UTF-8, and UCS-2 encodings are prede-
- fined.
+ The in-start-hex and in-end-hex fields (or the single in-hex
+ field) specify the Unicode range. The out-start-hex field (or
+ the out-hex field) specifies the start of the output encoding
+ range. The length of the out-start-hex (or out-hex) string
+ determines the length of the output characters (e.g., UTF-8 uses
+ different numbers of bytes to represent characters in different
+ ranges). Entries must be given in increasing Unicode order.
+ Only one file is allowed per encoding; the last specified file
+ is used. The Latin1, ASCII7, Symbol, ZapfDingbats, UTF-8, and
+ UCS-2 encodings are predefined.
cMapDir registry-ordering dir
- Specifies a search directory, dir, for CMaps for
- the registry-ordering character collection. There
- can be multiple directories for a particular col-
- lection. There are no default CMap directories.
+ Specifies a search directory, dir, for CMaps for the reg-
+ istry-ordering character collection. There can be multiple
+ directories for a particular collection. There are no default
+ CMap directories.
toUnicodeDir dir
- Specifies a search directory, dir, for ToUnicode
- CMaps. There can be multiple ToUnicode directo-
- ries. There are no default ToUnicode directories.
-
- ()
-
-2 ISPLAY_FONT
-
- displayFontT1 PDF-font-name T1-file
- Maps a PDF font, PDF-font-name, to a Type 1 font
- for display. The Type 1 font file, T1-file, should
- be a standard .pfa or .pfb file.
-
- displayFontTT PDF-font-name TT-file
- Maps a PDF font, PDF-font-name, to a TrueType font
- for display. The TrueType font file, TT-file,
- should be a standard .ttf file.
-
- displayNamedCIDFontT1 PDF-font-name T1-file
- Maps a specific PDF CID (16-bit) font,
- PDF-font-name, to a CID font (16-bit PostScript
- font), for display. There are no default CID font
- mappings.
-
- displayCIDFontT1 registry-ordering T1-file
- Maps the registry-ordering character collection to
- a CID font (16-bit PostScript font), for display.
- This mapping is used if the font name doesn't match
- any of the fonts declared with displayNamedCIDFont*
- commands. There are no default CID font mappings.
-
- displayNamedCIDFontTT PDF-font-name TT-file
- Maps a specific PDF CID (16-bit) font,
- PDF-font-name, to a (16-bit) TrueType font, for
- display. There are no default CID font mappings.
-
- displayCIDFontTT registry-ordering TT-file
- Maps the registry-ordering character collection to
- a (16-bit) TrueType font, for display. This map-
- ping is used if the font name doesn't match any of
- the fonts declared with displayNamedCIDFont* com-
- mands. There are no default CID font mappings.
+ Specifies a search directory, dir, for ToUnicode CMaps. There
+ can be multiple ToUnicode directories. There are no default
+ ToUnicode directories.
+
+ ()
+
+2 ENERAL_FONT_CONFIGURATIO
+
+ fontFile PDF-font-name font-file
+ Maps a PDF font, PDF-font-name, to a font for display or Post-
+ Script output. The font file, font-file, can be any type
+ allowed in a PDF file. This command can be used for 8-bit or
+ 16-bit (CID) fonts.
fontDir dir
- Specifies a search directory for external font
- files. There can be multiple fontDir directories.
- If a PDF file uses a font but doesn't embed it,
- these directories will be searched for a matching
- font file. These fonts are used by both xpdf (for
- display) and pdftops (for embedding in the gener-
- ated PostScript). Type 1 fonts must have a suffix
- of ".pfa", ".pfb", ".ps", or no suffix at all.
- TrueType fonts must have a ".ttf" suffix. Other
- files in these directories will be ignored. There
- are no default fontDir directories.
-
- ()
+ Specifies a search directory for font files. There can be mul-
+ tiple fontDir commands; all of the specified directories will be
+ searched in order. The font files can be Type 1 (.pfa or .pfb)
+ or TrueType (.ttf or .ttc); other files in the directory will be
+ ignored. The font file name (not including the extension) must
+ exactly match the PDF font name. This search is performed if
+ the font name doesn't match any of the fonts declared with the
+ fontFile command. There are no default fontDir directories.
+
+ fontFileCC registry-ordering font-file
+ Maps the registry-ordering character collection to a font for
+ display or PostScript output. This mapping is used if the font
+ name doesn't match any of the fonts declared with the fontFile,
+ fontDir, psResidentFont16, or psResidentFontCC commands.
+
+ ()
+
+2 OSTSCRIPT_FONT_CONFIGURATIO
+
+ psFontPassthrough yes | no
+ If set to "yes", pass 8-bit font names through to the PostScript
+ output without substitution. Fonts which are not embedded in
+ the PDF file are expected to be available on the printer. This
+ defaults to "no".
+
+ psResidentFont PDF-font-name PS-font-name
+ When the 8-bit font PDF-font-name is used (without embedding) in
+ a PDF file, it will be translated to the PostScript font
+ PS-font-name, which is assumed to be resident in the printer.
+ Typically, PDF-font-name and PS-font-name are the same. By
+ default, only the Base-14 fonts are assumed to be resident.
+
+ psResidentFont16 PDF-font-name wMode PS-font-name encoding
+ When the 16-bit (CID) font PDF-font-name with writing mode wMode
+ is used (without embedding) in a PDF file, it will be translated
+ to the PostScript font PS-font-name, which is assumbed to be
+ resident in the printer. The writing mode must be either 'H'
+ for horizontal or 'V' for vertical. The resident font is
+ assumed to use the specified encoding (which must have been
+ defined with the unicodeMap command).
+
+ psResidentFontCC registry-ordering wMode PS-font-name encoding
+ When a 16-bit (CID) font using the registry-ordering character
+ collection and wMode writing mode is used (without embedding) in
+ a PDF file, the PostScript font, PS-font-name, is substituted
+ for it. The substituted font is assumbed to be resident in the
+ printer. The writing mode must be either 'H' for horizontal or
+ 'V' for vertical. The resident font is assumed to use the spec-
+ ified encoding (which must have been defined with the unicodeMap
+ command).
+
+ psEmbedType1Fonts yes | no
+ If set to "no", prevents embedding of Type 1 fonts in generated
+ PostScript. This defaults to "yes".
+
+ psEmbedTrueTypeFonts yes | no
+ If set to "no", prevents embedding of TrueType fonts in gener-
+ ated PostScript. This defaults to "yes".
+
+ psEmbedCIDTrueTypeFonts yes | no
+ If set to "no", prevents embedding of CID TrueType fonts in gen-
+ erated PostScript. For Level 3 PostScript, this generates a CID
+ font, for lower levels it generates a non-CID composite font.
+ This defaults to "yes".
+
+ psEmbedCIDPostScriptFonts yes | no
+ If set to "no", prevents embedding of CID PostScript fonts in
+ generated PostScript. For Level 3 PostScript, this generates a
+ CID font, for lower levels it generates a non-CID composite
+ font. This defaults to "yes".
+
+ ()
2 OSTSCRIPT_CONTRO
psPaperSize width(pts) height(pts)
- Sets the paper size for PostScript output. The
- width and height parameters give the paper size in
- PostScript points (1 point = 1/72 inch).
+ Sets the paper size for PostScript output. The width and height
+ parameters give the paper size in PostScript points (1 point =
+ 1/72 inch).
psPaperSize letter | legal | A4 | A3 | match
- Sets the paper size for PostScript output to a
- standard size. The default paper size is set when
- xpdf and pdftops are built, typically to "letter"
- or "A4". This can also be set to "match", which
- will set the paper size to match the size specified
- in the PDF file.
+ Sets the paper size for PostScript output to a standard size.
+ The default paper size is set when xpdf and pdftops are built,
+ typically to "letter" or "A4". This can also be set to "match",
+ which will set the paper size to match the size specified in the
+ PDF file.
psImageableArea llx lly urx ury
- Sets the imageable area for PostScript output. The
- four integers are the coordinates of the lower-left
- and upper-right corners of the imageable region,
- specified in points (with the origin being the
- lower-left corner of the paper). This defaults to
- the full paper size; the psPaperSize option will
- reset the imageable area coordinates.
+ Sets the imageable area for PostScript output. The four inte-
+ gers are the coordinates of the lower-left and upper-right cor-
+ ners of the imageable region, specified in points (with the ori-
+ gin being the lower-left corner of the paper). This defaults to
+ the full paper size; the psPaperSize option will reset the
+ imageable area coordinates.
psCrop yes | no
- If set to "yes", PostScript output is cropped to
- the CropBox specified in the PDF file; otherwise no
- cropping is done. This defaults to "yes".
+ If set to "yes", PostScript output is cropped to the CropBox
+ specified in the PDF file; otherwise no cropping is done. This
+ defaults to "yes".
psExpandSmaller yes | no
- If set to "yes", PDF pages smaller than the
- PostScript imageable area are expanded to fill the
- imageable area. Otherwise, no scalling is done on
- smaller pages. This defaults to "no".
+ If set to "yes", PDF pages smaller than the PostScript imageable
+ area are expanded to fill the imageable area. Otherwise, no
+ scalling is done on smaller pages. This defaults to "no".
psShrinkLarger yes | no
- If set to yes, PDF pages larger than the PostScript
- imageable area are shrunk to fit the imageable
- area. Otherwise, no scaling is done on larger
- pages. This defaults to "yes".
+ If set to yes, PDF pages larger than the PostScript imageable
+ area are shrunk to fit the imageable area. Otherwise, no scal-
+ ing is done on larger pages. This defaults to "yes".
psCenter yes | no
- If set to yes, PDF pages smaller than the
- PostScript imageable area (after any scaling) are
- centered in the imageable area. Otherwise, they
- are aligned at the lower-left corner of the image-
- able area. This defaults to "yes".
+ If set to yes, PDF pages smaller than the PostScript imageable
+ area (after any scaling) are centered in the imageable area.
+ Otherwise, they are aligned at the lower-left corner of the
+ imageable area. This defaults to "yes".
psDuplex yes | no
- If set to "yes", the generated PostScript will set
- the "Duplex" pagedevice entry. This tells duplex-
- capable printers to enable duplexing. This
- defaults to "no".
+ If set to "yes", the generated PostScript will set the "Duplex"
+ pagedevice entry. This tells duplex-capable printers to enable
+ duplexing. This defaults to "no".
- psLevel level1 | level1sep | level2 | level2sep | level3 |
- level3Sep
- Sets the PostScript level to generate. This
- defaults to "level2".
-
- psFont PDF-font-name PS-font-name
- When the PDF-font-name font is used in a PDF file,
- it will be translated to the PostScript font
- PS-font-name, which is assumed to be resident in
- the printer. Typically, PDF-font-name and
- PS-font-name are the same. By default, only the
- Base-14 fonts are assumed to be resident.
-
- psNamedFont16 PDF-font-name wMode PS-font-name encoding
- When the 16-bit font PDF-font-name is used in a PDF
- file with the wMode writing mode and is not embed-
- ded, the PS-font-name font is substituted for it.
- The writing mode must be either 'H' for horizontal
- or 'V' for vertical. The PS-font-name font is
- assumed to be resident in the printer and to use
- the specified encoding (which must have been
- defined with the unicodeMap command).
-
- psFont16 registry-ordering wMode PS-font-name encoding
- When a 16-bit font using the registry-ordering
- character collection and wMode writing mode is not
- embedded and does not match any of the fonts
- declared in psNamedFont16 commands, the
- PS-font-name font is substituted for it. The writ-
- ing mode must be either 'H' for horizontal or 'V'
- for vertical. The PS-font-name font is assumed to
- be resident in the printer and to use the specified
- writing mode and encoding (which must have been
- defined with the unicodeMap command).
-
- psEmbedType1Fonts yes | no
- If set to "no", prevents embedding of Type 1 fonts
- in generated PostScript. This defaults to "yes".
-
- psEmbedTrueTypeFonts yes | no
- If set to "no", prevents embedding of TrueType
- fonts in generated PostScript. This defaults to
- "yes".
-
- psEmbedCIDTrueTypeFonts yes | no
- If set to "no", prevents embedding of CID TrueType
- fonts in generated PostScript. For Level 3
- PostScript, this generates a CID font, for lower
- levels it generates a non-CID composite font.
-
- psEmbedCIDPostScriptFonts yes | no
- If set to "no", prevents embedding of CID
- PostScript fonts in generated PostScript. For
- Level 3 PostScript, this generates a CID font, for
- lower levels it generates a non-CID composite font.
+ psLevel level1 | level1sep | level2 | level2sep | level3 | level3Sep
+ Sets the PostScript level to generate. This defaults to
+ "level2".
psPreload yes | no
- If set to "yes", PDF forms are converted to PS pro-
- cedures, and image data is preloaded. This uses
- more memory in the PostScript interpreter, but gen-
- erates significantly smaller PS files in situations
- where, e.g., the same image is drawn on every page
+ If set to "yes", PDF forms are converted to PS procedures, and
+ image data is preloaded. This uses more memory in the Post-
+ Script interpreter, but generates significantly smaller PS files
+ in situations where, e.g., the same image is drawn on every page
of a long document. This defaults to "no".
psOPI yes | no
- If set to "yes", generates PostScript OPI comments
- for all images and forms which have OPI informa-
- tion. This option is only available if the Xpdf
- tools were compiled with OPI support. This
- defaults to "no".
+ If set to "yes", generates PostScript OPI comments for all
+ images and forms which have OPI information. This option is
+ only available if the Xpdf tools were compiled with OPI support.
+ This defaults to "no".
psASCIIHex yes | no
- If set to "yes", the ASCIIHexEncode filter will be
- used instead of ASCII85Encode for binary data.
- This defaults to "no".
+ If set to "yes", the ASCIIHexEncode filter will be used instead
+ of ASCII85Encode for binary data. This defaults to "no".
+
+ psUncompressPreloadedImages yes | no
+ If set to "yes", all preloaded images in PS files will uncom-
+ pressed. If set to "no", the original compressed images will be
+ used when possible. The "yes" setting is useful to work around
+ certain buggy PostScript interpreters. This defaults to "no".
+
+ psRasterResolution float
+ Set the resolution (in dpi) for rasterized pages in PostScript
+ output. (Pdftops will rasterize pages which use transparency.)
+ This defaults to 300.
+
+ psRasterMono yes | no
+ If set to "yes", rasterized pages in PS files will be monochrome
+ (8-bit gray) instead of color. This defaults to "no".
+
+ psAlwaysRasterize yes | no
+ If set to "yes", all PostScript output will be rasterized. This
+ defaults to "no".
psFile file-or-command
- Sets the default PostScript file or print command
- for xpdf. Commands start with a '|' character;
- anything else is a file. If the file name or com-
- mand contains spaces it must be quoted. This
- defaults to unset, which tells xpdf to generate a
- name of the form <file>.ps for a PDF file
- <file>.pdf.
+ Sets the default PostScript file or print command for xpdf.
+ Commands start with a '|' character; anything else is a file.
+ If the file name or command contains spaces it must be quoted.
+ This defaults to unset, which tells xpdf to generate a name of
+ the form <file>.ps for a PDF file <file>.pdf.
fontDir dir
- See the description above, in the DISPLAY FONTS
- section.
+ See the description above, in the DISPLAY FONTS section.
- ()
+ ()
2 EXT_CONTRO
textEncoding encoding-name
- Sets the encoding to use for text output. (This
- can be overridden with the "-enc" switch on the
- command line.) The encoding-name must be defined
- with the unicodeMap command (see above). This
- defaults to "Latin1".
+ Sets the encoding to use for text output. (This can be overrid-
+ den with the "-enc" switch on the command line.) The encod-
+ ing-name must be defined with the unicodeMap command (see
+ above). This defaults to "Latin1".
textEOL unix | dos | mac
- Sets the end-of-line convention to use for text
- output. The options are:
+ Sets the end-of-line convention to use for text output. The
+ options are:
unix = LF
dos = CR+LF
mac = CR
- (This can be overridden with the "-eol" switch on
- the command line.) The default value is based on
- the OS where xpdf and pdftotext were built.
+ (This can be overridden with the "-eol" switch on the command
+ line.) The default value is based on the OS where xpdf and
+ pdftotext were built.
textPageBreaks yes | no
- If set to "yes", text extraction will insert page
- breaks (form feed characters) between pages. This
- defaults to "yes".
+ If set to "yes", text extraction will insert page breaks (form
+ feed characters) between pages. This defaults to "yes".
textKeepTinyChars yes | no
- If set to "yes", text extraction will keep all
- characters. If set to "no", text extraction will
- discard tiny (smaller than 3 point) characters
- after the first 50000 per page, avoiding extremely
- slow run times for PDF files that use special fonts
- to do shading or cross-hatching. This defaults to
- "no".
+ If set to "yes", text extraction will keep all characters. If
+ set to "no", text extraction will discard tiny (smaller than 3
+ point) characters after the first 50000 per page, avoiding
+ extremely slow run times for PDF files that use special fonts to
+ do shading or cross-hatching. This defaults to "no".
- ()
+ ()
2 ISCELLANEOUS_SETTING
initialZoom percentage | page | width
- Sets the initial zoom factor. A number specifies a
- zoom percentage, where 100 means 72 dpi. You may
- also specify 'page', to fit the page to the window
- size, or 'width', to fit the page width to the win-
- dow width.
+ Sets the initial zoom factor. A number specifies a zoom per-
+ centage, where 100 means 72 dpi. You may also specify 'page',
+ to fit the page to the window size, or 'width', to fit the page
+ width to the window width.
continuousView yes | no
- If set to "yes", xpdf will start in continuous view
- mode, i.e., with one vertical screoll bar for the
- whole document. This defaults to "no".
+ If set to "yes", xpdf will start in continuous view mode, i.e.,
+ with one vertical screoll bar for the whole document. This
+ defaults to "no".
enableT1lib yes | no
- Enables or disables use of t1lib (a Type 1 font
- rasterizer). This is only relevant if the Xpdf
- tools were built with t1lib support.
- ("enableT1lib" replaces the old "t1libControl"
+ Enables or disables use of t1lib (a Type 1 font rasterizer).
+ This is only relevant if the Xpdf tools were built with t1lib
+ support. ("enableT1lib" replaces the old "t1libControl"
option.) This option defaults to "yes".
enableFreeType yes | no
- Enables or disables use of FreeType (a TrueType /
- Type 1 font rasterizer). This is only relevant if
- the Xpdf tools were built with FreeType support.
- ("enableFreeType" replaces the old "freetypeCon-
- trol" option.) This option defaults to "yes".
+ Enables or disables use of FreeType (a TrueType / Type 1 font
+ rasterizer). This is only relevant if the Xpdf tools were built
+ with FreeType support. ("enableFreeType" replaces the old
+ "freetypeControl" option.) This option defaults to "yes".
+
+ enableFreeType yes | no
+ Enables or disables use of FreeType (a TrueType / Type 1 font
+ rasterizer). This is only relevant if the Xpdf tools were built
+ with FreeType support. ("enableFreeType" replaces the old
+ "freetypeControl" option.) This option defaults to "yes".
+
+ disableFreeTypeHinting yes | no
+ If this is set to "yes", FreeType hinting will be forced off.
+ This option defaults to "no".
antialias yes | no
- Enables or disables font anti-aliasing in the PDF
- rasterizer. This option affects all font rasteriz-
- ers. ("antialias" replaces the anti-aliasing con-
- trol provided by the old "t1libControl" and
+ Enables or disables font anti-aliasing in the PDF rasterizer.
+ This option affects all font rasterizers. ("antialias" replaces
+ the anti-aliasing control provided by the old "t1libControl" and
"freetypeControl" options.) This default to "yes".
vectorAntialias yes | no
- Enables or disables anti-aliasing of vector graph-
- ics in the PDF rasterizer. This defaults to "yes".
+ Enables or disables anti-aliasing of vector graphics in the PDF
+ rasterizer. This defaults to "yes".
+
+ antialiasPrinting yes | no
+ If this is "yes", bitmaps sent to the printer will be
+ antialiased (according to the "antialias" and "vectorAntialias"
+ settings). If this is "no", printed bitmaps will not be
+ antialiased. This defaults to "no".
strokeAdjust yes | no
- Enables or disables stroke adjustment. This
+ Enables or disables stroke adjustment. Stroke adjustment moves
+ horizontal and vertical lines by up to half a pixel to make them
+ look "cleaner" when vector anti-aliasing is enabled. This
defaults to "yes".
screenType dispersed | clustered | stochasticClustered
- Sets the halftone screen type, which will be used
- when generating a monochrome (1-bit) bitmap. The
- three options are dispersed-dot dithering, clus-
- tered-dot dithering (with a round dot and 45-degree
- screen angle), and stochastic clustered-dot dither-
- ing. By default, "stochasticClustered" is used for
- resolutions of 300 dpi and higher, and "dispersed"
- is used for resolutions lower then 300 dpi.
+ Sets the halftone screen type, which will be used when generat-
+ ing a monochrome (1-bit) bitmap. The three options are dis-
+ persed-dot dithering, clustered-dot dithering (with a round dot
+ and 45-degree screen angle), and stochastic clustered-dot
+ dithering. By default, "stochasticClustered" is used for reso-
+ lutions of 300 dpi and higher, and "dispersed" is used for reso-
+ lutions lower then 300 dpi.
screenSize integer
- Sets the size of the (square) halftone screen
- threshold matrix. By default, this is 4 for dis-
- persed-dot dithering, 10 for clustered-dot dither-
- ing, and 100 for stochastic clustered-dot dither-
- ing.
+ Sets the size of the (square) halftone screen threshold matrix.
+ By default, this is 4 for dispersed-dot dithering, 10 for clus-
+ tered-dot dithering, and 100 for stochastic clustered-dot
+ dithering.
screenDotRadius integer
- Sets the halftone screen dot radius. This is only
- used when screenType is set to stochasticClustered,
- and it defaults to 2. In clustered-dot mode, the
- dot radius is half of the screen size. Dispersed-
- dot dithering doesn't have a dot radius.
+ Sets the halftone screen dot radius. This is only used when
+ screenType is set to stochasticClustered, and it defaults to 2.
+ In clustered-dot mode, the dot radius is half of the screen
+ size. Dispersed-dot dithering doesn't have a dot radius.
screenGamma float
- Sets the halftone screen gamma correction parame-
- ter. Gamma values greater than 1 make the output
- brighter; gamma values less than 1 make it darker.
- The default value is 1.
+ Sets the halftone screen gamma correction parameter. Gamma val-
+ ues greater than 1 make the output brighter; gamma values less
+ than 1 make it darker. The default value is 1.
screenBlackThreshold float
- When halftoning, all values below this threshold
- are forced to solid black. This parameter is a
- floating point value between 0 (black) and 1
- (white). The default value is 0.
+ When halftoning, all values below this threshold are forced to
+ solid black. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 0.
screenWhiteThreshold float
- When halftoning, all values above this threshold
- are forced to solid white. This parameter is a
- floating point value between 0 (black) and 1
- (white). The default value is 1.
+ When halftoning, all values above this threshold are forced to
+ solid white. This parameter is a floating point value between 0
+ (black) and 1 (white). The default value is 1.
+
+ minLineWidth float
+ Set the minimum line width, in device pixels. This affects the
+ rasterizer only, not the PostScript converter (except when it
+ uses rasterization to handle transparency). The default value
+ is 0 (no minimum).
+
+ drawAnnotations yes | no
+ If set to "no", annotations will not be drawn or printed. The
+ default value is "yes".
+
+ overprintPreview yes | no
+ If set to "yes", generate overprint preview output, honoring the
+ OP/op/OPM settings in the PDF file. Ignored for non-CMYK out-
+ put. The default value is "no".
+
+ launchCommand command
+ Sets the command executed when you click on a "launch"-type
+ link. The intent is for the command to be a program/script
+ which determines the file type and runs the appropriate viewer.
+ The command line will consist of the file to be launched, fol-
+ lowed by any parameters specified with the link. Do not use
+ "%s" in "command". By default, this is unset, and Xpdf will
+ simply try to execute the file (after prompting the user).
urlCommand command
- Sets the command executed when you click on a URL
- link. The string "%s" will be replaced with the
- URL. (See the example below.) This has no default
- value.
+ Sets the command executed when you click on a URL link. The
+ string "%s" will be replaced with the URL. (See the example
+ below.) This has no default value.
movieCommand command
- Sets the command executed when you click on a movie
- annotation. The string "%s" will be replaced with
- the movie file name. This has no default value.
+ Sets the command executed when you click on a movie annotation.
+ The string "%s" will be replaced with the movie file name. This
+ has no default value.
mapNumericCharNames yes | no
- If set to "yes", the Xpdf tools will attempt to map
- various numeric character names sometimes used in
- font subsets. In some cases this leads to usable
- text, and in other cases it leads to gibberish --
- there is no way for Xpdf to tell. This defaults to
+ If set to "yes", the Xpdf tools will attempt to map various
+ numeric character names sometimes used in font subsets. In some
+ cases this leads to usable text, and in other cases it leads to
+ gibberish -- there is no way for Xpdf to tell. This defaults to
"yes".
mapUnknownCharNames yes | no
- If set to "yes", and mapNumericCharNames is set to
- "no", the Xpdf tools will apply a simple pass-
- through mapping (Unicode index = character code)
- for all unrecognized glyph names. In some cases,
- this leads to usable text, and in other cases it
- leads to gibberish -- there is no way for Xpdf to
- tell. This defaults to "no".
+ If set to "yes", and mapNumericCharNames is set to "no", the
+ Xpdf tools will apply a simple pass-through mapping (Unicode
+ index = character code) for all unrecognized glyph names. (For
+ CID fonts, setting mapNumericCharNames to "no" is unnecessary.)
+ In some cases, this leads to usable text, and in other cases it
+ leads to gibberish -- there is no way for Xpdf to tell. This
+ defaults to "no".
bind modifiers-key context command ...
- Add a key or mouse button binding. Modifiers can
- be zero or more of:
+ Add a key or mouse button binding. Modifiers can be zero or
+ more of:
shift-
ctrl-
alt-
- Key can be a regular ASCII character, or any one
- of:
+ Key can be a regular ASCII character, or any one of:
space
tab
@@ -479,25 +478,23 @@
mousePress1 .. mousePress7 (mouse buttons)
mouseRelease1 .. mouseRelease7 (mouse buttons)
- Context is either "any" or a comma-separated combi-
- nation of:
+ Context is either "any" or a comma-separated combination of:
fullScreen / window (full screen mode on/off)
continuous / singlePage (continuous mode on/off)
overLink / offLink (mouse over link or not)
scrLockOn / scrLockOff (scroll lock on/off)
- The context string can include only one of each
- pair in the above list.
+ The context string can include only one of each pair in the
+ above list.
- Command is an Xpdf command (see the COMMANDS sec-
- tion of the xpdf(1) man page for details). Multi-
- ple commands are separated by whitespace.
+ Command is an Xpdf command (see the COMMANDS section of the
+ xpdf(1) man page for details). Multiple commands are separated
+ by whitespace.
- The bind command replaces any existing binding, but
- only if it was defined for the exact same modi-
- fiers, key, and context. All tokens (modifiers,
- key, context, commands) are case-sensitive.
+ The bind command replaces any existing binding, but only if it
+ was defined for the exact same modifiers, key, and context. All
+ tokens (modifiers, key, context, commands) are case-sensitive.
Example key bindings:
@@ -513,24 +510,21 @@
See the xpdf(1) man page for more examples.
unbind modifiers-key context
- Removes a key binding established with the bind
- command. This is most useful to remove default key
- bindings before establishing new ones (e.g., if the
- default key binding is given for "any" context, and
- you want to create new key bindings for multiple
- contexts).
+ Removes a key binding established with the bind command. This
+ is most useful to remove default key bindings before establish-
+ ing new ones (e.g., if the default key binding is given for
+ "any" context, and you want to create new key bindings for mul-
+ tiple contexts).
printCommands yes | no
- If set to "yes", drawing commands are printed as
- they're executed (useful for debugging). This
- defaults to "no".
+ If set to "yes", drawing commands are printed as they're exe-
+ cuted (useful for debugging). This defaults to "no".
errQuiet yes | no
- If set to "yes", this suppresses all error and
- warning messages from all of the Xpdf tools. This
- defaults to "no".
+ If set to "yes", this suppresses all error and warning messages
+ from all of the Xpdf tools. This defaults to "no".
- ()
+ ()
2 EXAMPLES
@@ -545,20 +539,20 @@
cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1
# use the Base-14 Type 1 fonts from ghostscript
- displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
- displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
- displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
- displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
- displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
- displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
- displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
- displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
- displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
- displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
- displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
- displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
- displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
- displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+ fontFile Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+ fontFile Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+ fontFile Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+ fontFile Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+ fontFile Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+ fontFile Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+ fontFile Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+ fontFile Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+ fontFile Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+ fontFile Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+ fontFile Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+ fontFile Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+ fontFile Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+ fontFile ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
# use the Bakoma Type 1 fonts
# (this assumes they happen to be installed in /usr/local/fonts/bakoma)
@@ -574,46 +568,45 @@
# assume that the PostScript printer has the Univers and
# Univers-Bold fonts
- psFont Univers Univers
- psFont Univers-Bold Univers-Bold
+ psResidentFont Univers Univers
+ psResidentFont Univers-Bold Univers-Bold
# set the text output options
textEncoding UTF-8
textEOL unix
# misc options
- t1libControl low
- freetypeControl low
+ enableT1lib yes
+ enableFreeType yes
+ launchCommand viewer-script
urlCommand "netscape -remote 'openURL(%s)'"
- ()
+ ()
2 FILES
/usr/local/etc/xpdfrc
- This is the default location for the system-wide
- configuration file. Depending on build options, it
- may be placed elsewhere.
+ This is the default location for the system-wide configuration
+ file. Depending on build options, it may be placed elsewhere.
$HOME/.xpdfrc
- This is the user's configuration file. If it
- exists, it will be read in place of the system-wide
- file.
+ This is the user's configuration file. If it exists, it will be
+ read in place of the system-wide file.
- ()
+ ()
2 AUTHOR
- The Xpdf software and documentation are copyright
- 1996-2007 Glyph & Cog, LLC.
+ The Xpdf software and documentation are copyright 1996-2011 Glyph &
+ Cog, LLC.
- ()
+ ()
2 SEE_ALSO
- xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1),
- pdftoppm(1), pdfimages(1)
+ xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde-
+ tach(1), pdftoppm(1), pdfimages(1)
http://www.foolabs.com/xpdf/
- ()
+ ()
diff --git a/fofi/FoFiBase.cc b/fofi/FoFiBase.cc
index 28d0b8c..4adef2a 100644
--- a/fofi/FoFiBase.cc
+++ b/fofi/FoFiBase.cc
@@ -13,6 +13,7 @@
#endif
#include <stdio.h>
+#include <limits.h>
#include "gmem.h"
#include "FoFiBase.h"
@@ -42,6 +43,10 @@ char *FoFiBase::readFile(char *fileName, int *fileLen) {
}
fseek(f, 0, SEEK_END);
n = (int)ftell(f);
+ if (n < 0) {
+ fclose(f);
+ return NULL;
+ }
fseek(f, 0, SEEK_SET);
buf = (char *)gmalloc(n);
if ((int)fread(buf, 1, n, f) != n) {
@@ -79,7 +84,7 @@ int FoFiBase::getU8(int pos, GBool *ok) {
int FoFiBase::getS16BE(int pos, GBool *ok) {
int x;
- if (pos < 0 || pos+1 >= len) {
+ if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
*ok = gFalse;
return 0;
}
@@ -94,7 +99,7 @@ int FoFiBase::getS16BE(int pos, GBool *ok) {
int FoFiBase::getU16BE(int pos, GBool *ok) {
int x;
- if (pos < 0 || pos+1 >= len) {
+ if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
*ok = gFalse;
return 0;
}
@@ -106,7 +111,7 @@ int FoFiBase::getU16BE(int pos, GBool *ok) {
int FoFiBase::getS32BE(int pos, GBool *ok) {
int x;
- if (pos < 0 || pos+3 >= len) {
+ if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
*ok = gFalse;
return 0;
}
@@ -123,7 +128,7 @@ int FoFiBase::getS32BE(int pos, GBool *ok) {
Guint FoFiBase::getU32BE(int pos, GBool *ok) {
Guint x;
- if (pos < 0 || pos+3 >= len) {
+ if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
*ok = gFalse;
return 0;
}
@@ -134,11 +139,25 @@ Guint FoFiBase::getU32BE(int pos, GBool *ok) {
return x;
}
+Guint FoFiBase::getU32LE(int pos, GBool *ok) {
+ Guint x;
+
+ if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos+3];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos];
+ return x;
+}
+
Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) {
Guint x;
int i;
- if (pos < 0 || pos + size > len) {
+ if (pos < 0 || pos + size > len || pos > INT_MAX - size) {
*ok = gFalse;
return 0;
}
diff --git a/fofi/FoFiBase.h b/fofi/FoFiBase.h
index b78840b..c9f93eb 100644
--- a/fofi/FoFiBase.h
+++ b/fofi/FoFiBase.h
@@ -19,7 +19,7 @@
//------------------------------------------------------------------------
-typedef void (*FoFiOutputFunc)(void *stream, char *data, int len);
+typedef void (*FoFiOutputFunc)(void *stream, const char *data, int len);
//------------------------------------------------------------------------
// FoFiBase
@@ -44,6 +44,7 @@ protected:
int getU16BE(int pos, GBool *ok);
int getS32BE(int pos, GBool *ok);
Guint getU32BE(int pos, GBool *ok);
+ Guint getU32LE(int pos, GBool *ok);
Guint getUVarBE(int pos, int size, GBool *ok);
GBool checkRegion(int pos, int size);
diff --git a/fofi/FoFiEncodings.cc b/fofi/FoFiEncodings.cc
index 37a17f5..e654fab 100644
--- a/fofi/FoFiEncodings.cc
+++ b/fofi/FoFiEncodings.cc
@@ -19,7 +19,7 @@
// Type 1 and 1C font data
//------------------------------------------------------------------------
-char *fofiType1StandardEncoding[256] = {
+const char *fofiType1StandardEncoding[256] = {
NULL,
NULL,
NULL,
@@ -278,7 +278,7 @@ char *fofiType1StandardEncoding[256] = {
NULL
};
-char *fofiType1ExpertEncoding[256] = {
+const char *fofiType1ExpertEncoding[256] = {
NULL,
NULL,
NULL,
@@ -541,7 +541,7 @@ char *fofiType1ExpertEncoding[256] = {
// Type 1C font data
//------------------------------------------------------------------------
-char *fofiType1CStdStrings[391] = {
+const char *fofiType1CStdStrings[391] = {
".notdef",
"space",
"exclam",
diff --git a/fofi/FoFiEncodings.h b/fofi/FoFiEncodings.h
index 50e285d..dd85458 100644
--- a/fofi/FoFiEncodings.h
+++ b/fofi/FoFiEncodings.h
@@ -21,14 +21,14 @@
// Type 1 and 1C font data
//------------------------------------------------------------------------
-extern char *fofiType1StandardEncoding[256];
-extern char *fofiType1ExpertEncoding[256];
+extern const char *fofiType1StandardEncoding[256];
+extern const char *fofiType1ExpertEncoding[256];
//------------------------------------------------------------------------
// Type 1C font data
//------------------------------------------------------------------------
-extern char *fofiType1CStdStrings[391];
+extern const char *fofiType1CStdStrings[391];
extern Gushort fofiType1CISOAdobeCharset[229];
extern Gushort fofiType1CExpertCharset[166];
extern Gushort fofiType1CExpertSubsetCharset[87];
diff --git a/fofi/FoFiIdentifier.cc b/fofi/FoFiIdentifier.cc
new file mode 100644
index 0000000..10ac486
--- /dev/null
+++ b/fofi/FoFiIdentifier.cc
@@ -0,0 +1,632 @@
+//========================================================================
+//
+// FoFiIdentifier.cc
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "gtypes.h"
+#include "FoFiIdentifier.h"
+
+//------------------------------------------------------------------------
+
+class Reader {
+public:
+
+ virtual ~Reader() {}
+
+ // Read one byte. Returns -1 if past EOF.
+ virtual int getByte(int pos) = 0;
+
+ // Read a big-endian unsigned 16-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU16BE(int pos, int *val) = 0;
+
+ // Read a big-endian unsigned 32-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU32BE(int pos, Guint *val) = 0;
+
+ // Read a little-endian unsigned 32-bit integer. Fills in *val and
+ // returns true if successful.
+ virtual GBool getU32LE(int pos, Guint *val) = 0;
+
+ // Read a big-endian unsigned <size>-byte integer, where 1 <= size
+ // <= 4. Fills in *val and returns true if successful.
+ virtual GBool getUVarBE(int pos, int size, Guint *val) = 0;
+
+ // Compare against a string. Returns true if equal.
+ virtual GBool cmp(int pos, const char *s) = 0;
+
+};
+
+//------------------------------------------------------------------------
+
+class MemReader: public Reader {
+public:
+
+ static MemReader *make(char *bufA, int lenA);
+ virtual ~MemReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ MemReader(char *bufA, int lenA);
+
+ char *buf;
+ int len;
+};
+
+MemReader *MemReader::make(char *bufA, int lenA) {
+ return new MemReader(bufA, lenA);
+}
+
+MemReader::MemReader(char *bufA, int lenA) {
+ buf = bufA;
+ len = lenA;
+}
+
+MemReader::~MemReader() {
+}
+
+int MemReader::getByte(int pos) {
+ if (pos < 0 || pos >= len) {
+ return -1;
+ }
+ return buf[pos] & 0xff;
+}
+
+GBool MemReader::getU16BE(int pos, int *val) {
+ if (pos < 0 || pos > len - 2) {
+ return gFalse;
+ }
+ *val = ((buf[pos] & 0xff) << 8) +
+ (buf[pos+1] & 0xff);
+ return gTrue;
+}
+
+GBool MemReader::getU32BE(int pos, Guint *val) {
+ if (pos < 0 || pos > len - 4) {
+ return gFalse;
+ }
+ *val = ((buf[pos] & 0xff) << 24) +
+ ((buf[pos+1] & 0xff) << 16) +
+ ((buf[pos+2] & 0xff) << 8) +
+ (buf[pos+3] & 0xff);
+ return gTrue;
+}
+
+GBool MemReader::getU32LE(int pos, Guint *val) {
+ if (pos < 0 || pos > len - 4) {
+ return gFalse;
+ }
+ *val = (buf[pos] & 0xff) +
+ ((buf[pos+1] & 0xff) << 8) +
+ ((buf[pos+2] & 0xff) << 16) +
+ ((buf[pos+3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool MemReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || pos < 0 || pos > len - size) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool MemReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (pos < 0 || len < n || pos > len - n) {
+ return gFalse;
+ }
+ return !memcmp(buf + pos, s, n);
+}
+
+//------------------------------------------------------------------------
+
+class FileReader: public Reader {
+public:
+
+ static FileReader *make(char *fileName);
+ virtual ~FileReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ FileReader(FILE *fA);
+ GBool fillBuf(int pos, int len);
+
+ FILE *f;
+ char buf[1024];
+ int bufPos, bufLen;
+};
+
+FileReader *FileReader::make(char *fileName) {
+ FILE *fA;
+
+ if (!(fA = fopen(fileName, "rb"))) {
+ return NULL;
+ }
+ return new FileReader(fA);
+}
+
+FileReader::FileReader(FILE *fA) {
+ f = fA;
+ bufPos = 0;
+ bufLen = 0;
+}
+
+FileReader::~FileReader() {
+ fclose(f);
+}
+
+int FileReader::getByte(int pos) {
+ if (!fillBuf(pos, 1)) {
+ return -1;
+ }
+ return buf[pos - bufPos] & 0xff;
+}
+
+GBool FileReader::getU16BE(int pos, int *val) {
+ if (!fillBuf(pos, 2)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 8) +
+ (buf[pos - bufPos + 1] & 0xff);
+ return gTrue;
+}
+
+GBool FileReader::getU32BE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 24) +
+ ((buf[pos - bufPos + 1] & 0xff) << 16) +
+ ((buf[pos - bufPos + 2] & 0xff) << 8) +
+ (buf[pos - bufPos + 3] & 0xff);
+ return gTrue;
+}
+
+GBool FileReader::getU32LE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = (buf[pos - bufPos] & 0xff) +
+ ((buf[pos - bufPos + 1] & 0xff) << 8) +
+ ((buf[pos - bufPos + 2] & 0xff) << 16) +
+ ((buf[pos - bufPos + 3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool FileReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || !fillBuf(pos, size)) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool FileReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (!fillBuf(pos, n)) {
+ return gFalse;
+ }
+ return !memcmp(buf - bufPos + pos, s, n);
+}
+
+GBool FileReader::fillBuf(int pos, int len) {
+ if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
+ pos > INT_MAX - (int)sizeof(buf)) {
+ return gFalse;
+ }
+ if (pos >= bufPos && pos + len <= bufPos + bufLen) {
+ return gTrue;
+ }
+ if (fseek(f, pos, SEEK_SET)) {
+ return gFalse;
+ }
+ bufPos = pos;
+ bufLen = (int)fread(buf, 1, sizeof(buf), f);
+ if (bufLen < len) {
+ return gFalse;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+class StreamReader: public Reader {
+public:
+
+ static StreamReader *make(int (*getCharA)(void *data), void *dataA);
+ virtual ~StreamReader();
+ virtual int getByte(int pos);
+ virtual GBool getU16BE(int pos, int *val);
+ virtual GBool getU32BE(int pos, Guint *val);
+ virtual GBool getU32LE(int pos, Guint *val);
+ virtual GBool getUVarBE(int pos, int size, Guint *val);
+ virtual GBool cmp(int pos, const char *s);
+
+private:
+
+ StreamReader(int (*getCharA)(void *data), void *dataA);
+ GBool fillBuf(int pos, int len);
+
+ int (*getChar)(void *data);
+ void *data;
+ int streamPos;
+ char buf[1024];
+ int bufPos, bufLen;
+};
+
+StreamReader *StreamReader::make(int (*getCharA)(void *data), void *dataA) {
+ return new StreamReader(getCharA, dataA);
+}
+
+StreamReader::StreamReader(int (*getCharA)(void *data), void *dataA) {
+ getChar = getCharA;
+ data = dataA;
+ streamPos = 0;
+ bufPos = 0;
+ bufLen = 0;
+}
+
+StreamReader::~StreamReader() {
+}
+
+int StreamReader::getByte(int pos) {
+ if (!fillBuf(pos, 1)) {
+ return -1;
+ }
+ return buf[pos - bufPos] & 0xff;
+}
+
+GBool StreamReader::getU16BE(int pos, int *val) {
+ if (!fillBuf(pos, 2)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 8) +
+ (buf[pos - bufPos + 1] & 0xff);
+ return gTrue;
+}
+
+GBool StreamReader::getU32BE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = ((buf[pos - bufPos] & 0xff) << 24) +
+ ((buf[pos - bufPos + 1] & 0xff) << 16) +
+ ((buf[pos - bufPos + 2] & 0xff) << 8) +
+ (buf[pos - bufPos + 3] & 0xff);
+ return gTrue;
+}
+
+GBool StreamReader::getU32LE(int pos, Guint *val) {
+ if (!fillBuf(pos, 4)) {
+ return gFalse;
+ }
+ *val = (buf[pos - bufPos] & 0xff) +
+ ((buf[pos - bufPos + 1] & 0xff) << 8) +
+ ((buf[pos - bufPos + 2] & 0xff) << 16) +
+ ((buf[pos - bufPos + 3] & 0xff) << 24);
+ return gTrue;
+}
+
+GBool StreamReader::getUVarBE(int pos, int size, Guint *val) {
+ int i;
+
+ if (size < 1 || size > 4 || !fillBuf(pos, size)) {
+ return gFalse;
+ }
+ *val = 0;
+ for (i = 0; i < size; ++i) {
+ *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
+ }
+ return gTrue;
+}
+
+GBool StreamReader::cmp(int pos, const char *s) {
+ int n;
+
+ n = (int)strlen(s);
+ if (!fillBuf(pos, n)) {
+ return gFalse;
+ }
+ return !memcmp(buf - bufPos + pos, s, n);
+}
+
+GBool StreamReader::fillBuf(int pos, int len) {
+ int c;
+
+ if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
+ pos > INT_MAX - (int)sizeof(buf)) {
+ return gFalse;
+ }
+ if (pos < bufPos) {
+ return gFalse;
+ }
+
+ // if requested region will not fit in the current buffer...
+ if (pos + len > bufPos + (int)sizeof(buf)) {
+
+ // if the start of the requested data is already in the buffer, move
+ // it to the start of the buffer
+ if (pos < bufPos + bufLen) {
+ bufLen -= pos - bufPos;
+ memmove(buf, buf + (pos - bufPos), bufLen);
+ bufPos = pos;
+
+ // otherwise discard data from the
+ // stream until we get to the requested position
+ } else {
+ bufPos += bufLen;
+ bufLen = 0;
+ while (bufPos < pos) {
+ if ((c = (*getChar)(data)) < 0) {
+ return gFalse;
+ }
+ ++bufPos;
+ }
+ }
+ }
+
+ // read the rest of the requested data
+ while (bufPos + bufLen < pos + len) {
+ if ((c = (*getChar)(data)) < 0) {
+ return gFalse;
+ }
+ buf[bufLen++] = (char)c;
+ }
+
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+static FoFiIdentifierType identify(Reader *reader);
+static FoFiIdentifierType identifyOpenType(Reader *reader);
+static FoFiIdentifierType identifyCFF(Reader *reader, int start);
+
+FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) {
+ MemReader *reader;
+ FoFiIdentifierType type;
+
+ if (!(reader = MemReader::make(file, len))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+ return type;
+}
+
+FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) {
+ FileReader *reader;
+ FoFiIdentifierType type;
+
+ if (!(reader = FileReader::make(fileName))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+ return type;
+}
+
+FoFiIdentifierType FoFiIdentifier::identifyStream(int (*getChar)(void *data),
+ void *data) {
+ StreamReader *reader;
+ FoFiIdentifierType type;
+
+ if (!(reader = StreamReader::make(getChar, data))) {
+ return fofiIdError;
+ }
+ type = identify(reader);
+ delete reader;
+ return type;
+}
+
+static FoFiIdentifierType identify(Reader *reader) {
+ Guint n;
+
+ //----- PFA
+ if (reader->cmp(0, "%!PS-AdobeFont-1") ||
+ reader->cmp(0, "%!FontType1")) {
+ return fofiIdType1PFA;
+ }
+
+ //----- PFB
+ if (reader->getByte(0) == 0x80 &&
+ reader->getByte(1) == 0x01 &&
+ reader->getU32LE(2, &n)) {
+ if ((n >= 16 && reader->cmp(6, "%!PS-AdobeFont-1")) ||
+ (n >= 11 && reader->cmp(6, "%!FontType1"))) {
+ return fofiIdType1PFB;
+ }
+ }
+
+ //----- TrueType
+ if ((reader->getByte(0) == 0x00 &&
+ reader->getByte(1) == 0x01 &&
+ reader->getByte(2) == 0x00 &&
+ reader->getByte(3) == 0x00) ||
+ (reader->getByte(0) == 0x74 && // 'true'
+ reader->getByte(1) == 0x72 &&
+ reader->getByte(2) == 0x75 &&
+ reader->getByte(3) == 0x65)) {
+ return fofiIdTrueType;
+ }
+ if (reader->getByte(0) == 0x74 && // 'ttcf'
+ reader->getByte(1) == 0x74 &&
+ reader->getByte(2) == 0x63 &&
+ reader->getByte(3) == 0x66) {
+ return fofiIdTrueTypeCollection;
+ }
+
+ //----- OpenType
+ if (reader->getByte(0) == 0x4f && // 'OTTO
+ reader->getByte(1) == 0x54 &&
+ reader->getByte(2) == 0x54 &&
+ reader->getByte(3) == 0x4f) {
+ return identifyOpenType(reader);
+ }
+
+ //----- CFF
+ if (reader->getByte(0) == 0x01 &&
+ reader->getByte(1) == 0x00) {
+ return identifyCFF(reader, 0);
+ }
+ // some tools embed CFF fonts with an extra whitespace char at the
+ // beginning
+ if (reader->getByte(1) == 0x01 &&
+ reader->getByte(2) == 0x00) {
+ return identifyCFF(reader, 1);
+ }
+
+ return fofiIdUnknown;
+}
+
+static FoFiIdentifierType identifyOpenType(Reader *reader) {
+ FoFiIdentifierType type;
+ Guint offset;
+ int nTables, i;
+
+ if (!reader->getU16BE(4, &nTables)) {
+ return fofiIdUnknown;
+ }
+ for (i = 0; i < nTables; ++i) {
+ if (reader->cmp(12 + i*16, "CFF ")) {
+ if (reader->getU32BE(12 + i*16 + 8, &offset) &&
+ offset < (Guint)INT_MAX) {
+ type = identifyCFF(reader, (int)offset);
+ if (type == fofiIdCFF8Bit) {
+ type = fofiIdOpenTypeCFF8Bit;
+ } else if (type == fofiIdCFFCID) {
+ type = fofiIdOpenTypeCFFCID;
+ }
+ return type;
+ }
+ return fofiIdUnknown;
+ }
+ }
+ return fofiIdUnknown;
+}
+
+static FoFiIdentifierType identifyCFF(Reader *reader, int start) {
+ Guint offset0, offset1;
+ int hdrSize, offSize0, offSize1, pos, endPos, b0, n, i;
+
+ //----- read the header
+ if (reader->getByte(start) != 0x01 ||
+ reader->getByte(start + 1) != 0x00) {
+ return fofiIdUnknown;
+ }
+ if ((hdrSize = reader->getByte(start + 2)) < 0) {
+ return fofiIdUnknown;
+ }
+ if ((offSize0 = reader->getByte(start + 3)) < 1 || offSize0 > 4) {
+ return fofiIdUnknown;
+ }
+ pos = start + hdrSize;
+ if (pos < 0) {
+ return fofiIdUnknown;
+ }
+
+ //----- skip the name index
+ if (!reader->getU16BE(pos, &n)) {
+ return fofiIdUnknown;
+ }
+ if (n == 0) {
+ pos += 2;
+ } else {
+ if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
+ return fofiIdUnknown;
+ }
+ if (!reader->getUVarBE(pos + 3 + n * offSize1, offSize1, &offset1) ||
+ offset1 > (Guint)INT_MAX) {
+ return fofiIdUnknown;
+ }
+ pos += 3 + (n + 1) * offSize1 + (int)offset1 - 1;
+ }
+ if (pos < 0) {
+ return fofiIdUnknown;
+ }
+
+ //----- parse the top dict index
+ if (!reader->getU16BE(pos, &n) || n < 1) {
+ return fofiIdUnknown;
+ }
+ if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
+ return fofiIdUnknown;
+ }
+ if (!reader->getUVarBE(pos + 3, offSize1, &offset0) ||
+ offset0 > (Guint)INT_MAX ||
+ !reader->getUVarBE(pos + 3 + offSize1, offSize1, &offset1) ||
+ offset1 > (Guint)INT_MAX ||
+ offset0 > offset1) {
+ return fofiIdUnknown;
+ }
+ pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
+ endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
+ if (pos < 0 || endPos < 0 || pos > endPos) {
+ return fofiIdUnknown;
+ }
+
+ //----- parse the top dict, look for ROS as first entry
+ // for a CID font, the top dict starts with:
+ // <int> <int> <int> ROS
+ for (i = 0; i < 3; ++i) {
+ b0 = reader->getByte(pos++);
+ if (b0 == 0x1c) {
+ pos += 2;
+ } else if (b0 == 0x1d) {
+ pos += 4;
+ } else if (b0 >= 0xf7 && b0 <= 0xfe) {
+ pos += 1;
+ } else if (b0 < 0x20 || b0 > 0xf6) {
+ return fofiIdCFF8Bit;
+ }
+ if (pos >= endPos || pos < 0) {
+ return fofiIdCFF8Bit;
+ }
+ }
+ if (pos + 1 < endPos &&
+ reader->getByte(pos) == 12 &&
+ reader->getByte(pos + 1) == 30) {
+ return fofiIdCFFCID;
+ } else {
+ return fofiIdCFF8Bit;
+ }
+}
diff --git a/fofi/FoFiIdentifier.h b/fofi/FoFiIdentifier.h
new file mode 100644
index 0000000..79da845
--- /dev/null
+++ b/fofi/FoFiIdentifier.h
@@ -0,0 +1,44 @@
+//========================================================================
+//
+// FoFiIdentifier.h
+//
+// Copyright 2009 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIIDENTIFIER_H
+#define FOFIIDENTIFIER_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+//------------------------------------------------------------------------
+// FoFiIdentifier
+//------------------------------------------------------------------------
+
+enum FoFiIdentifierType {
+ fofiIdType1PFA, // Type 1 font in PFA format
+ fofiIdType1PFB, // Type 1 font in PFB format
+ fofiIdCFF8Bit, // 8-bit CFF font
+ fofiIdCFFCID, // CID CFF font
+ fofiIdTrueType, // TrueType font
+ fofiIdTrueTypeCollection, // TrueType collection
+ fofiIdOpenTypeCFF8Bit, // OpenType wrapper with 8-bit CFF font
+ fofiIdOpenTypeCFFCID, // OpenType wrapper with CID CFF font
+ fofiIdUnknown, // unknown type
+ fofiIdError // error in reading the file
+};
+
+class FoFiIdentifier {
+public:
+
+ static FoFiIdentifierType identifyMem(char *file, int len);
+ static FoFiIdentifierType identifyFile(char *fileName);
+ static FoFiIdentifierType identifyStream(int (*getChar)(void *data),
+ void *data);
+};
+
+#endif
diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
index f8a1aa3..6503fda 100644
--- a/fofi/FoFiTrueType.cc
+++ b/fofi/FoFiTrueType.cc
@@ -14,6 +14,9 @@
#include <stdlib.h>
#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
#include "gtypes.h"
#include "gmem.h"
#include "GString.h"
@@ -116,6 +119,31 @@ struct TrueTypeLoca {
#define os2Tag 0x4f532f32
#define postTag 0x706f7374
+#ifdef HAVE_STD_SORT
+
+struct cmpTrueTypeLocaOffsetFunctor {
+ bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
+ if (loca1.origOffset == loca2.origOffset) {
+ return loca1.idx < loca2.idx;
+ }
+ return loca1.origOffset < loca2.origOffset;
+ }
+};
+
+struct cmpTrueTypeLocaIdxFunctor {
+ bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
+ return loca1.idx < loca2.idx;
+ }
+};
+
+struct cmpTrueTypeTableTagFunctor {
+ bool operator()(const TrueTypeTable &tab1, const TrueTypeTable &tab2) {
+ return tab1.tag < tab2.tag;
+ }
+};
+
+#else // HAVE_STD_SORT
+
static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
@@ -140,10 +168,12 @@ static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
return (int)tab1->tag - (int)tab2->tag;
}
+#endif // HAVE_STD_SORT
+
//------------------------------------------------------------------------
struct T42Table {
- char *tag; // 4-byte tag
+ const char *tag; // 4-byte tag
GBool required; // required by the TrueType spec?
};
@@ -173,7 +203,7 @@ static T42Table t42Tables[nT42Tables] = {
// Glyph names in some arbitrary standard order that Apple uses for
// their TrueType fonts.
-static char *macGlyphNames[258] = {
+static const char *macGlyphNames[258] = {
".notdef", "null", "CR", "space",
"exclam", "quotedbl", "numbersign", "dollar",
"percent", "ampersand", "quotesingle", "parenleft",
@@ -316,8 +346,8 @@ int FoFiTrueType::findCmap(int platform, int encoding) {
return -1;
}
-Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
- Gushort gid;
+int FoFiTrueType::mapCodeToGID(int i, int c) {
+ int gid;
int segCnt, segEnd, segStart, segDelta, segOffset;
int cmapFirst, cmapLen;
int pos, a, b, m;
@@ -365,7 +395,7 @@ Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
gid = (c + segDelta) & 0xffff;
} else {
gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
- segOffset + 2 * (c - segStart), &ok);
+ segOffset + 2 * (c - segStart), &ok);
if (gid != 0) {
gid = (gid + segDelta) & 0xffff;
}
@@ -395,21 +425,32 @@ int FoFiTrueType::mapNameToGID(char *name) {
return nameToGID->lookupInt(name);
}
-Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
- FoFiType1C *ff;
- Gushort *map;
+GBool FoFiTrueType::getCFFBlock(char **start, int *length) {
int i;
- *nCIDs = 0;
if (!openTypeCFF) {
- return NULL;
+ return gFalse;
}
i = seekTable("CFF ");
if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return gFalse;
+ }
+ *start = (char *)file + tables[i].offset;
+ *length = tables[i].len;
+ return gTrue;
+}
+
+int *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+ int *map;
+
+ *nCIDs = 0;
+ if (!getCFFBlock(&start, &length)) {
return NULL;
}
- if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
- tables[i].len))) {
+ if (!(ff = FoFiType1C::make(start, length))) {
return NULL;
}
map = ff->getCIDToGIDMap(nCIDs);
@@ -441,11 +482,27 @@ int FoFiTrueType::getEmbeddingRights() {
return 3;
}
+void FoFiTrueType::getFontMatrix(double *mat) {
+ char *start;
+ int length;
+ FoFiType1C *ff;
+
+ if (!getCFFBlock(&start, &length)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make(start, length))) {
+ return;
+ }
+ ff->getFontMatrix(mat);
+ delete ff;
+}
+
void FoFiTrueType::convertToType42(char *psName, char **encoding,
- Gushort *codeToGID,
+ int *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream) {
GString *buf;
+ int maxUsedGlyph;
GBool ok;
if (openTypeCFF) {
@@ -462,7 +519,7 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding,
// begin the font dictionary
(*outputFunc)(outputStream, "10 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
@@ -475,27 +532,23 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding,
// write the guts of the dictionary
cvtEncoding(encoding, outputFunc, outputStream);
cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
- cvtSfnts(outputFunc, outputStream, NULL, gFalse);
+ cvtSfnts(outputFunc, outputStream, NULL, gFalse, &maxUsedGlyph);
// end the dictionary and define the font
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
-void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
+void FoFiTrueType::convertToType1(char *psName, const char **newEncoding,
GBool ascii, FoFiOutputFunc outputFunc,
void *outputStream) {
+ char *start;
+ int length;
FoFiType1C *ff;
- int i;
- if (!openTypeCFF) {
+ if (!getCFFBlock(&start, &length)) {
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))) {
+ if (!(ff = FoFiType1C::make(start, length))) {
return;
}
ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
@@ -503,12 +556,12 @@ void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
}
void FoFiTrueType::convertToCIDType2(char *psName,
- Gushort *cidMap, int nCIDs,
+ int *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
GString *buf;
- Gushort cid;
+ int cid, maxUsedGlyph;
GBool ok;
int i, j, k;
@@ -526,7 +579,7 @@ void FoFiTrueType::convertToCIDType2(char *psName,
// begin the font dictionary
(*outputFunc)(outputStream, "20 dict begin\n", 14);
(*outputFunc)(outputStream, "/CIDFontName /", 14);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
@@ -624,7 +677,7 @@ void FoFiTrueType::convertToCIDType2(char *psName,
(*outputFunc)(outputStream, " end readonly def\n", 19);
// write the guts of the dictionary
- cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
+ cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics, &maxUsedGlyph);
// end the dictionary and define the font
(*outputFunc)(outputStream,
@@ -632,34 +685,30 @@ void FoFiTrueType::convertToCIDType2(char *psName,
56);
}
-void FoFiTrueType::convertToCIDType0(char *psName,
+void FoFiTrueType::convertToCIDType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc,
void *outputStream) {
+ char *start;
+ int length;
FoFiType1C *ff;
- int i;
- if (!openTypeCFF) {
- return;
- }
- i = seekTable("CFF ");
- if (!checkRegion(tables[i].offset, tables[i].len)) {
+ if (!getCFFBlock(&start, &length)) {
return;
}
- if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
- tables[i].len))) {
+ if (!(ff = FoFiType1C::make(start, length))) {
return;
}
- ff->convertToCIDType0(psName, outputFunc, outputStream);
+ ff->convertToCIDType0(psName, cidMap, nCIDs, outputFunc, outputStream);
delete ff;
}
-void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
GString *buf;
GString *sfntsName;
- int n, i, j;
+ int maxUsedGlyph, n, i, j;
if (openTypeCFF) {
return;
@@ -667,15 +716,36 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
// write the Type 42 sfnts array
sfntsName = (new GString(psName))->append("_sfnts");
- cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
+ cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics,
+ &maxUsedGlyph);
delete sfntsName;
// write the descendant Type 42 fonts
- n = cidMap ? nCIDs : nGlyphs;
+ // (The following is a kludge: nGlyphs is the glyph count from the
+ // maxp table; maxUsedGlyph is the max glyph number that has a
+ // non-zero-length description, from the loca table. The problem is
+ // that some TrueType font subsets fail to change the glyph count,
+ // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
+ // in an unnecessarily huge Type 0 font. But some other PDF files
+ // have fonts with only zero or one used glyph, and a content stream
+ // that refers to one of the unused glyphs -- this results in PS
+ // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
+ // we compromise by always defining at least 256 glyphs.)
+ if (cidMap) {
+ n = nCIDs;
+ } else if (nGlyphs > maxUsedGlyph + 256) {
+ if (maxUsedGlyph <= 255) {
+ n = 256;
+ } else {
+ n = maxUsedGlyph + 1;
+ }
+ } else {
+ n = nGlyphs;
+ }
for (i = 0; i < n; i += 256) {
(*outputFunc)(outputStream, "10 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
buf = GString::format("_{0:02x} def\n", i >> 8);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -687,7 +757,7 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
(*outputFunc)(outputStream, "/sfnts ", 7);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, "_sfnts def\n", 11);
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
for (j = 0; j < 256 && i+j < n; ++j) {
@@ -712,7 +782,7 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
// write the Type 0 parent font
(*outputFunc)(outputStream, "16 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 0 def\n", 16);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
@@ -727,7 +797,7 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
for (i = 0; i < n; i += 256) {
(*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
buf = GString::format("_{0:02x} findfont\n", i >> 8);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -736,38 +806,37 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
-void FoFiTrueType::convertToType0(char *psName,
+void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc,
void *outputStream) {
+ char *start;
+ int length;
FoFiType1C *ff;
- int i;
- if (!openTypeCFF) {
- return;
- }
- i = seekTable("CFF ");
- if (!checkRegion(tables[i].offset, tables[i].len)) {
+ if (!getCFFBlock(&start, &length)) {
return;
}
- if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
- tables[i].len))) {
+ if (!(ff = FoFiType1C::make(start, length))) {
return;
}
- ff->convertToType0(psName, outputFunc, outputStream);
+ ff->convertToType0(psName, cidMap, nCIDs, outputFunc, outputStream);
delete ff;
}
void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
void *outputStream, char *name,
- Gushort *codeToGID) {
- // this substitute cmap table maps char codes 0000-ffff directly to
- // glyphs 0000-ffff
- static char cmapTab[36] = {
+ int *codeToGID) {
+ // this substitute cmap table maps char code ffff to glyph 0,
+ // with tables for MacRoman and MS Unicode
+ static char cmapTab[44] = {
0, 0, // table version number
- 0, 1, // number of encoding tables
+ 0, 2, // number of encoding tables
0, 1, // platform ID
0, 0, // encoding ID
- 0, 0, 0, 12, // offset of subtable
+ 0, 0, 0, 20, // offset of subtable
+ 0, 3, // platform ID
+ 0, 1, // encoding ID
+ 0, 0, 0, 20, // offset of subtable
0, 4, // subtable format
0, 24, // subtable length
0, 0, // subtable version
@@ -777,9 +846,9 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
0, 0, // 2*segCount - 2*2^floor(log2(segCount))
(char)0xff, (char)0xff, // endCount[0]
0, 0, // reserved
- 0, 0, // startCount[0]
- 0, 0, // idDelta[0]
- 0, 0 // pad to a mulitple of four bytes
+ (char)0xff, (char)0xff, // startCount[0]
+ 0, 1, // idDelta[0]
+ 0, 0 // idRangeOffset[0]
};
static char nameTab[8] = {
0, 0, // format
@@ -801,8 +870,8 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
static char os2Tab[86] = {
0, 1, // version
0, 1, // xAvgCharWidth
- 0, 0, // usWeightClass
- 0, 0, // usWidthClass
+ 0x01, (char)0x90, // usWeightClass
+ 0, 5, // usWidthClass
0, 0, // fsType
0, 0, // ySubscriptXSize
0, 0, // ySubscriptYSize
@@ -828,14 +897,14 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
0, 0, // sTypoAscender
0, 0, // sTypoDescender
0, 0, // sTypoLineGap
- 0, 0, // usWinAscent
- 0, 0, // usWinDescent
- 0, 0, 0, 0, // ulCodePageRange1
+ 0x20, 0x00, // usWinAscent
+ 0x20, 0x00, // usWinDescent
+ 0, 0, 0, 1, // ulCodePageRange1
0, 0, 0, 0 // ulCodePageRange2
};
GBool missingCmap, missingName, missingPost, missingOS2;
- GBool unsortedLoca, badCmapLen, abbrevHMTX;
- int nZeroLengthTables;
+ GBool unsortedLoca, emptyCmap, badCmapLen, abbrevHMTX;
+ int nZeroLengthTables, nBogusTables;
int nHMetrics, advWidth, lsb;
TrueTypeLoca *locaTable;
TrueTypeTable *newTables;
@@ -895,27 +964,50 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
locaTable[i].idx = i;
}
- // check for zero-length tables
- nZeroLengthTables = 0;
+ // check for zero-length tables and bogus tags
+ nZeroLengthTables = nBogusTables = 0;
for (i = 0; i < nTables; ++i) {
if (tables[i].len == 0) {
++nZeroLengthTables;
+ if (tables[i].tag == cmapTag) {
+ missingCmap = gTrue;
+ } else if (tables[i].tag == nameTag) {
+ missingName = gTrue;
+ } else if (tables[i].tag == postTag) {
+ missingPost = gTrue;
+ } else if (tables[i].tag == os2Tag) {
+ missingOS2 = gTrue;
+ }
+ } else if (!(tables[i].tag & 0xe0000000) ||
+ !(tables[i].tag & 0x00e00000) ||
+ !(tables[i].tag & 0x0000e000) ||
+ !(tables[i].tag & 0x000000e0)) {
+ // tags where any of the bytes are < 0x20 are probably bogus
+ // (the TrueType spec uses ASCII sequences for tags) -- this
+ // catches problems where the number of tables given in the
+ // header is too large, and so gibberish data is read at the end
+ // of the table directory
+ ++nBogusTables;
}
}
- // check for an incorrect cmap table length
- badCmapLen = gFalse;
+ // check for an empty cmap table or an incorrect cmap table length
+ emptyCmap = badCmapLen = gFalse;
cmapLen = 0; // make gcc happy
if (!missingCmap) {
- cmapLen = cmaps[0].offset + cmaps[0].len;
- for (i = 1; i < nCmaps; ++i) {
- if (cmaps[i].offset + cmaps[i].len > cmapLen) {
- cmapLen = cmaps[i].offset + cmaps[i].len;
+ if (nCmaps == 0) {
+ emptyCmap = gTrue;
+ } else {
+ cmapLen = cmaps[0].offset + cmaps[0].len;
+ for (i = 1; i < nCmaps; ++i) {
+ if (cmaps[i].offset + cmaps[i].len > cmapLen) {
+ cmapLen = cmaps[i].offset + cmaps[i].len;
+ }
+ }
+ cmapLen -= tables[cmapIdx].offset;
+ if (cmapLen > tables[cmapIdx].len) {
+ badCmapLen = gTrue;
}
- }
- cmapLen -= tables[cmapIdx].offset;
- if (cmapLen > tables[cmapIdx].len) {
- badCmapLen = gTrue;
}
}
@@ -928,7 +1020,8 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
// if nothing is broken, just write the TTF file as is
if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
- !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
+ !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX &&
+ nZeroLengthTables == 0 && nBogusTables == 0 &&
!name && !codeToGID) {
(*outputFunc)(outputStream, (char *)file, len);
goto done1;
@@ -942,14 +1035,27 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
// the same pos value remain in the same order)
glyfLen = 0; // make gcc happy
if (unsortedLoca) {
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1,
+ cmpTrueTypeLocaOffsetFunctor());
+#else
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
&cmpTrueTypeLocaOffset);
+#endif
for (i = 0; i < nGlyphs; ++i) {
locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
}
locaTable[nGlyphs].len = 0;
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
+#else
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
&cmpTrueTypeLocaIdx);
+#endif
+ // if the last entry in the loca is not the max offset (size of
+ // the glyf table), something is wrong -- work around the problem
+ // by forcing the last sorted entry to have a zero length
+ locaTable[nGlyphs].len = 0;
pos = 0;
for (i = 0; i <= nGlyphs; ++i) {
locaTable[i].newOffset = pos;
@@ -990,7 +1096,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
// construct the new name table
if (name) {
- n = strlen(name);
+ n = (int)strlen(name);
newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
newNameTab = (char *)gmalloc(newNameLen);
memset(newNameTab, 0, newNameLen);
@@ -1079,8 +1185,16 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newCmapTab[42] = 0; // idRangeOffset[1]
newCmapTab[43] = 0;
for (i = 0; i < 256; ++i) {
- newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
- newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
+ if (codeToGID[i] < 0) {
+ //~ this may not be correct - we want this character to never be
+ //~ displayed, but mapping it to the notdef glyph may result in
+ //~ little boxes being displayed
+ newCmapTab[44 + 2*i] = 0;
+ newCmapTab[44 + 2*i + 1] = 0;
+ } else {
+ newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
+ newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
+ }
}
} else {
newCmapLen = 0;
@@ -1132,16 +1246,20 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
// - sort the table by tag
// - compute new table positions, including 4-byte alignment
// - (re)compute table checksums
- nNewTables = nTables - nZeroLengthTables +
+ nNewTables = nTables - nZeroLengthTables - nBogusTables +
(missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
(missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
j = 0;
for (i = 0; i < nTables; ++i) {
- if (tables[i].len > 0) {
+ if (tables[i].len > 0 &&
+ (tables[i].tag & 0xe0000000) &&
+ (tables[i].tag & 0x00e00000) &&
+ (tables[i].tag & 0x0000e000) &&
+ (tables[i].tag & 0x000000e0)) {
newTables[j] = tables[i];
newTables[j].origOffset = tables[i].offset;
- if (checkRegion(tables[i].offset, newTables[i].len)) {
+ if (checkRegion(tables[i].offset, tables[i].len)) {
newTables[j].checksum =
computeTableChecksum(file + tables[i].offset, tables[i].len);
if (tables[i].tag == headTag) {
@@ -1153,6 +1271,10 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newTables[j].len = newCmapLen;
newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
newCmapLen);
+ } else if (newTables[j].tag == cmapTag && emptyCmap) {
+ newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
+ sizeof(cmapTab));
+ newTables[j].len = sizeof(cmapTab);
} else if (newTables[j].tag == cmapTag && badCmapLen) {
newTables[j].len = cmapLen;
} else if (newTables[j].tag == locaTag && unsortedLoca) {
@@ -1217,8 +1339,12 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newTables[j].len = sizeof(os2Tab);
++j;
}
+#if HAVE_STD_SORT
+ std::sort(newTables, newTables + nNewTables, cmpTrueTypeTableTagFunctor());
+#else
qsort(newTables, nNewTables, sizeof(TrueTypeTable),
&cmpTrueTypeTableTag);
+#endif
pos = 12 + nNewTables * 16;
for (i = 0; i < nNewTables; ++i) {
newTables[i].offset = pos;
@@ -1369,7 +1495,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
void FoFiTrueType::cvtEncoding(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char *name;
+ const char *name;
GString *buf;
int i;
@@ -1382,7 +1508,7 @@ void FoFiTrueType::cvtEncoding(char **encoding,
buf = GString::format("dup {0:d} /", i);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
- (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, name, (int)strlen(name));
(*outputFunc)(outputStream, " put\n", 5);
}
} else {
@@ -1396,7 +1522,7 @@ void FoFiTrueType::cvtEncoding(char **encoding,
}
void FoFiTrueType::cvtCharStrings(char **encoding,
- Gushort *codeToGID,
+ int *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream) {
char *name;
@@ -1435,7 +1561,7 @@ void FoFiTrueType::cvtCharStrings(char **encoding,
// test
if (k > 0 && k < nGlyphs) {
(*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, name, (int)strlen(name));
buf = GString::format(" {0:d} def\n", k);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -1449,7 +1575,8 @@ void FoFiTrueType::cvtCharStrings(char **encoding,
void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
void *outputStream, GString *name,
- GBool needVerticalMetrics) {
+ GBool needVerticalMetrics,
+ int *maxUsedGlyph) {
Guchar headData[54];
TrueTypeLoca *locaTable;
Guchar *locaData;
@@ -1458,7 +1585,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
GBool ok;
Guint checksum;
int nNewTables;
- int length, pos, glyfPos, i, j, k;
+ int glyfTableLen, length, pos, glyfPos, i, j, k;
Guchar vheaTab[36] = {
0, 1, 0, 0, // table version number
0, 0, // ascent
@@ -1491,16 +1618,25 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
memcpy(headData, file + pos, 54);
headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
+ // check for a bogus loca format field in the 'head' table
+ // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
+ if (locaFmt != 0 && locaFmt != 1) {
+ headData[50] = 0;
+ headData[51] = 1;
+ }
+
// read the original 'loca' table, pad entries out to 4 bytes, and
// sort it into proper order -- some (non-compliant) fonts have
// out-of-order loca tables; in order to correctly handle the case
// where (compliant) fonts have empty entries in the middle of the
- // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
+ // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
// and idx as its secondary key (ensuring that adjacent entries with
// the same pos value remain in the same order)
locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
i = seekTable("loca");
pos = tables[i].offset;
+ i = seekTable("glyf");
+ glyfTableLen = tables[i].len;
ok = gTrue;
for (i = 0; i <= nGlyphs; ++i) {
locaTable[i].idx = i;
@@ -1509,22 +1645,38 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
} else {
locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
}
+ if (locaTable[i].origOffset > glyfTableLen) {
+ locaTable[i].origOffset = glyfTableLen;
+ }
}
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1,
+ cmpTrueTypeLocaOffsetFunctor());
+#else
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
&cmpTrueTypeLocaOffset);
+#endif
for (i = 0; i < nGlyphs; ++i) {
locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
}
locaTable[nGlyphs].len = 0;
+#if HAVE_STD_SORT
+ std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
+#else
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
&cmpTrueTypeLocaIdx);
+#endif
pos = 0;
+ *maxUsedGlyph = -1;
for (i = 0; i <= nGlyphs; ++i) {
locaTable[i].newOffset = pos;
pos += locaTable[i].len;
if (pos & 3) {
pos += 4 - (pos & 3);
}
+ if (locaTable[i].len > 0) {
+ *maxUsedGlyph = i;
+ }
}
// construct the new 'loca' table
@@ -1607,7 +1759,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
length = sizeof(vheaTab);
checksum = computeTableChecksum(vheaTab, length);
} else if (needVerticalMetrics && i == t42VmtxTable) {
- length = 4 + (nGlyphs - 1) * 4;
+ length = 4 + (nGlyphs - 1) * 2;
vmtxTab = (Guchar *)gmalloc(length);
vmtxTab[0] = advance / 256;
vmtxTab[1] = advance % 256;
@@ -1725,7 +1877,6 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
dumpString(vheaTab, length, outputFunc, outputStream);
} else if (needVerticalMetrics && i == t42VmtxTable) {
dumpString(vmtxTab, length, outputFunc, outputStream);
- gfree(vmtxTab);
}
}
}
@@ -1736,6 +1887,9 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
gfree(locaData);
gfree(locaTable);
+ if (vmtxTab) {
+ gfree(vmtxTab);
+ }
}
void FoFiTrueType::dumpString(Guchar *s, int length,
@@ -1830,17 +1984,20 @@ void FoFiTrueType::parse() {
}
tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
pos += 12;
+ j = 0;
for (i = 0; i < nTables; ++i) {
- tables[i].tag = getU32BE(pos, &parsedOk);
- tables[i].checksum = getU32BE(pos + 4, &parsedOk);
- tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
- tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
- if (tables[i].offset + tables[i].len < tables[i].offset ||
- tables[i].offset + tables[i].len > len) {
- parsedOk = gFalse;
+ tables[j].tag = getU32BE(pos, &parsedOk);
+ tables[j].checksum = getU32BE(pos + 4, &parsedOk);
+ tables[j].offset = (int)getU32BE(pos + 8, &parsedOk);
+ tables[j].len = (int)getU32BE(pos + 12, &parsedOk);
+ if (tables[j].offset + tables[j].len >= tables[j].offset &&
+ tables[j].offset + tables[j].len <= len) {
+ // ignore any bogus entries in the table directory
+ ++j;
}
pos += 16;
}
+ nTables = j;
if (!parsedOk) {
return;
}
@@ -2010,7 +2167,7 @@ void FoFiTrueType::readPostTable() {
}
}
-int FoFiTrueType::seekTable(char *tag) {
+int FoFiTrueType::seekTable(const char *tag) {
Guint tagI;
int i;
diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h
index cf06ae7..53d5062 100644
--- a/fofi/FoFiTrueType.h
+++ b/fofi/FoFiTrueType.h
@@ -56,7 +56,7 @@ public:
int findCmap(int platform, int encoding);
// Return the GID corresponding to <c> according to the <i>th cmap.
- Gushort mapCodeToGID(int i, int c);
+ int mapCodeToGID(int i, int c);
// Returns the GID corresponding to <name> according to the post
// table. Returns 0 if there is no mapping for <name> or if the
@@ -66,7 +66,7 @@ public:
// 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);
+ int *getCIDToGIDMap(int *nCIDs);
// Returns the least restrictive embedding licensing right (as
// defined by the TrueType spec):
@@ -77,6 +77,10 @@ public:
// * 0: restricted license embedding
int getEmbeddingRights();
+ // Return the font matrix as an array of six numbers. (Only useful
+ // for OpenType CFF fonts.)
+ void getFontMatrix(double *mat);
+
// Convert to a Type 42 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
@@ -85,7 +89,7 @@ public:
// <codeToGID> array specifies the mapping from char codes to GIDs.
// (Not useful for OpenType CFF fonts.)
void convertToType42(char *psName, char **encoding,
- Gushort *codeToGID,
+ int *codeToGID,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 1 font, suitable for embedding in a PostScript
@@ -95,7 +99,7 @@ public:
// 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,
+ void convertToType1(char *psName, const char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 2 CIDFont, suitable for embedding in a
@@ -103,14 +107,14 @@ public:
// 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. (Not useful for OpenType CFF fonts.)
- void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
+ void convertToCIDType2(char *psName, int *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,
+ void convertToCIDType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
@@ -118,14 +122,14 @@ public:
// 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. (Not useful for OpenType CFF fonts.)
- void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+ void convertToType0(char *psName, int *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,
+ void convertToType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc, void *outputStream);
// Write a clean TTF file, filling in missing tables and correcting
@@ -135,7 +139,12 @@ public:
// 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);
+ char *name = NULL, int *codeToGID = NULL);
+
+ // Returns a pointer to the CFF font embedded in this OpenType font.
+ // If successful, sets *<start> and *<length>, and returns true.
+ // Otherwise returns false. (Only useful for OpenType CFF fonts).
+ GBool getCFFBlock(char **start, int *length);
private:
@@ -144,19 +153,20 @@ private:
FoFiOutputFunc outputFunc,
void *outputStream);
void cvtCharStrings(char **encoding,
- Gushort *codeToGID,
+ int *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream);
void cvtSfnts(FoFiOutputFunc outputFunc,
void *outputStream, GString *name,
- GBool needVerticalMetrics);
+ GBool needVerticalMetrics,
+ int *maxUsedGlyph);
void dumpString(Guchar *s, int length,
FoFiOutputFunc outputFunc,
void *outputStream);
Guint computeTableChecksum(Guchar *data, int length);
void parse();
void readPostTable();
- int seekTable(char *tag);
+ int seekTable(const char *tag);
TrueTypeTable *tables;
int nTables;
diff --git a/fofi/FoFiType1.cc b/fofi/FoFiType1.cc
index efad5ee..9eeb363 100644
--- a/fofi/FoFiType1.cc
+++ b/fofi/FoFiType1.cc
@@ -41,7 +41,14 @@ FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
{
name = NULL;
encoding = NULL;
+ fontMatrix[0] = 0.001;
+ fontMatrix[1] = 0;
+ fontMatrix[2] = 0;
+ fontMatrix[3] = 0.001;
+ fontMatrix[4] = 0;
+ fontMatrix[5] = 0;
parsed = gFalse;
+ undoPFB();
}
FoFiType1::~FoFiType1() {
@@ -50,7 +57,7 @@ FoFiType1::~FoFiType1() {
if (name) {
gfree(name);
}
- if (encoding && encoding != fofiType1StandardEncoding) {
+ if (encoding && encoding != (char **)fofiType1StandardEncoding) {
for (i = 0; i < 256; ++i) {
gfree(encoding[i]);
}
@@ -72,7 +79,18 @@ char **FoFiType1::getEncoding() {
return encoding;
}
-void FoFiType1::writeEncoded(char **newEncoding,
+void FoFiType1::getFontMatrix(double *mat) {
+ int i;
+
+ if (!parsed) {
+ parse();
+ }
+ for (i = 0; i < 6; ++i) {
+ mat[i] = fontMatrix[i];
+ }
+}
+
+void FoFiType1::writeEncoded(const char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream) {
char buf[512];
char *line, *line2, *p;
@@ -87,7 +105,7 @@ void FoFiType1::writeEncoded(char **newEncoding,
(*outputFunc)(outputStream, (char *)file, len);
return;
}
- (*outputFunc)(outputStream, (char *)file, line - (char *)file);
+ (*outputFunc)(outputStream, (char *)file, (int)(line - (char *)file));
// write the new encoding
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
@@ -96,7 +114,7 @@ void FoFiType1::writeEncoded(char **newEncoding,
for (i = 0; i < 256; ++i) {
if (newEncoding[i]) {
sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf, (int)strlen(buf));
}
}
(*outputFunc)(outputStream, "readonly def\n", 13);
@@ -128,7 +146,7 @@ void FoFiType1::writeEncoded(char **newEncoding,
i < 20 && line2 && strncmp(line2, "/Encoding", 9);
line2 = getNextLine(line2), ++i) ;
if (i < 20 && line2) {
- (*outputFunc)(outputStream, line, line2 - line);
+ (*outputFunc)(outputStream, line, (int)(line2 - line));
if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line2);
} else {
@@ -150,7 +168,7 @@ void FoFiType1::writeEncoded(char **newEncoding,
// copy everything after the encoding
if (line) {
- (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ (*outputFunc)(outputStream, line, (int)(((char *)file + len) - line));
}
}
}
@@ -175,8 +193,10 @@ void FoFiType1::parse() {
char *line, *line1, *p, *p2;
char buf[256];
char c;
- int n, code, i, j;
+ int n, code, base, i, j;
+ GBool gotMatrix;
+ gotMatrix = gFalse;
for (i = 1, line = (char *)file;
i <= 100 && line && (!name || !encoding);
++i) {
@@ -194,7 +214,7 @@ void FoFiType1::parse() {
// get encoding
} else if (!encoding &&
!strncmp(line, "/Encoding StandardEncoding def", 30)) {
- encoding = fofiType1StandardEncoding;
+ encoding = (char **)fofiType1StandardEncoding;
} else if (!encoding &&
!strncmp(line, "/Encoding 256 array", 19)) {
encoding = (char **)gmallocn(256, sizeof(char *));
@@ -204,34 +224,47 @@ void FoFiType1::parse() {
for (j = 0, line = getNextLine(line);
j < 300 && line && (line1 = getNextLine(line));
++j, line = line1) {
- if ((n = line1 - line) > 255) {
+ if ((n = (int)(line1 - line)) > 255) {
n = 255;
}
strncpy(buf, line, n);
buf[n] = '\0';
for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
if (!strncmp(p, "dup", 3)) {
- for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
- for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
- if (*p2) {
- c = *p2;
- *p2 = '\0';
- code = atoi(p);
- *p2 = c;
- if (code == 8 && *p2 == '#') {
- code = 0;
- for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
- code = code * 8 + (*p2 - '0');
- }
+ while (1) {
+ p += 3;
+ for (; *p == ' ' || *p == '\t'; ++p) ;
+ code = 0;
+ if (*p == '8' && p[1] == '#') {
+ base = 8;
+ p += 2;
+ } else if (*p >= '0' && *p <= '9') {
+ base = 10;
+ } else {
+ break;
+ }
+ for (; *p >= '0' && *p < '0' + base; ++p) {
+ code = code * base + (*p - '0');
+ }
+ for (; *p == ' ' || *p == '\t'; ++p) ;
+ if (*p != '/') {
+ break;
+ }
+ ++p;
+ for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+ if (code >= 0 && code < 256) {
+ c = *p2;
+ *p2 = '\0';
+ encoding[code] = copyString(p);
+ *p2 = c;
}
- if (code < 256) {
- for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
- if (*p == '/') {
- ++p;
- for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
- *p2 = '\0';
- encoding[code] = copyString(p);
- }
+ for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+ if (strncmp(p, "put", 3)) {
+ break;
+ }
+ for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+ if (strncmp(p, "dup", 3)) {
+ break;
}
}
} else {
@@ -243,6 +276,24 @@ void FoFiType1::parse() {
}
//~ check for getinterval/putinterval junk
+ } else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) {
+ strncpy(buf, line + 11, 255);
+ buf[255] = '\0';
+ if ((p = strchr(buf, '['))) {
+ ++p;
+ if ((p2 = strchr(p, ']'))) {
+ *p2 = '\0';
+ for (j = 0; j < 6; ++j) {
+ if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
+ fontMatrix[j] = atof(p);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ gotMatrix = gTrue;
+
} else {
line = getNextLine(line);
}
@@ -250,3 +301,38 @@ void FoFiType1::parse() {
parsed = gTrue;
}
+
+// Undo the PFB encoding, i.e., remove the PFB headers.
+void FoFiType1::undoPFB() {
+ GBool ok;
+ Guchar *file2;
+ int pos1, pos2, type;
+ Guint segLen;
+
+ ok = gTrue;
+ if (getU8(0, &ok) != 0x80 || !ok) {
+ return;
+ }
+ file2 = (Guchar *)gmalloc(len);
+ pos1 = pos2 = 0;
+ while (getU8(pos1, &ok) == 0x80 && ok) {
+ type = getU8(pos1 + 1, &ok);
+ if (type < 1 || type > 2 || !ok) {
+ break;
+ }
+ segLen = getU32LE(pos1 + 2, &ok);
+ pos1 += 6;
+ if (!ok || !checkRegion(pos1, segLen)) {
+ break;
+ }
+ memcpy(file2 + pos2, file + pos1, segLen);
+ pos1 += segLen;
+ pos2 += segLen;
+ }
+ if (freeFileData) {
+ gfree(fileData);
+ }
+ file = fileData = file2;
+ freeFileData = gTrue;
+ len = pos2;
+}
diff --git a/fofi/FoFiType1.h b/fofi/FoFiType1.h
index 843352b..4a64f24 100644
--- a/fofi/FoFiType1.h
+++ b/fofi/FoFiType1.h
@@ -40,8 +40,11 @@ public:
// be NULL).
char **getEncoding();
+ // Return the font matrix as an array of six numbers.
+ void getFontMatrix(double *mat);
+
// Write a version of the Type 1 font file with a new encoding.
- void writeEncoded(char **newEncoding,
+ void writeEncoded(const char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream);
private:
@@ -50,9 +53,11 @@ private:
char *getNextLine(char *line);
void parse();
+ void undoPFB();
char *name;
char **encoding;
+ double fontMatrix[6];
GBool parsed;
};
diff --git a/fofi/FoFiType1C.cc b/fofi/FoFiType1C.cc
index 3b28f32..93af207 100644
--- a/fofi/FoFiType1C.cc
+++ b/fofi/FoFiType1C.cc
@@ -72,8 +72,8 @@ FoFiType1C::~FoFiType1C() {
delete name;
}
if (encoding &&
- encoding != fofiType1StandardEncoding &&
- encoding != fofiType1ExpertEncoding) {
+ encoding != (char **)fofiType1StandardEncoding &&
+ encoding != (char **)fofiType1ExpertEncoding) {
for (i = 0; i < 256; ++i) {
gfree(encoding[i]);
}
@@ -101,8 +101,20 @@ char **FoFiType1C::getEncoding() {
return encoding;
}
-Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
- Gushort *map;
+GString *FoFiType1C::getGlyphName(int gid) {
+ char buf[256];
+ GBool ok;
+
+ ok = gTrue;
+ getString(charset[gid], buf, &ok);
+ if (!ok) {
+ return NULL;
+ }
+ return new GString(buf);
+}
+
+int *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
+ int *map;
int n, i;
// a CID font's top dict has ROS as the first operator
@@ -120,8 +132,8 @@ Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
}
}
++n;
- map = (Gushort *)gmallocn(n, sizeof(Gushort));
- memset(map, 0, n * sizeof(Gushort));
+ map = (int *)gmallocn(n, sizeof(int));
+ memset(map, 0, n * sizeof(int));
for (i = 0; i < nGlyphs; ++i) {
map[charset[i]] = i;
}
@@ -129,8 +141,37 @@ Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
return map;
}
-void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
- FoFiOutputFunc outputFunc,
+void FoFiType1C::getFontMatrix(double *mat) {
+ int i;
+
+ if (topDict.firstOp == 0x0c1e && privateDicts[0].hasFontMatrix) {
+ if (topDict.hasFontMatrix) {
+ mat[0] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[1] * privateDicts[0].fontMatrix[2];
+ mat[1] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[1] * privateDicts[0].fontMatrix[3];
+ mat[2] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[3] * privateDicts[0].fontMatrix[2];
+ mat[3] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[3] * privateDicts[0].fontMatrix[3];
+ mat[4] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[0] +
+ topDict.fontMatrix[5] * privateDicts[0].fontMatrix[2];
+ mat[5] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[1] +
+ topDict.fontMatrix[5] * privateDicts[0].fontMatrix[3];
+ } else {
+ for (i = 0; i < 6; ++i) {
+ mat[i] = privateDicts[0].fontMatrix[i];
+ }
+ }
+ } else {
+ for (i = 0; i < 6; ++i) {
+ mat[i] = topDict.fontMatrix[i];
+ }
+ }
+}
+
+void FoFiType1C::convertToType1(char *psName, const char **newEncoding,
+ GBool ascii, FoFiOutputFunc outputFunc,
void *outputStream) {
int psNameLen;
Type1CEexecBuf eb;
@@ -138,12 +179,12 @@ void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
Type1CIndexVal val;
GString *buf;
char buf2[256];
- char **enc;
+ const char **enc;
GBool ok;
int i;
if (psName) {
- psNameLen = strlen(psName);
+ psNameLen = (int)strlen(psName);
} else {
psName = name->getCString();
psNameLen = name->getLength();
@@ -155,7 +196,7 @@ void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
(*outputFunc)(outputStream, psName, psNameLen);
if (topDict.versionSID != 0) {
getString(topDict.versionSID, buf2, &ok);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
}
(*outputFunc)(outputStream, "\n", 1);
// the dictionary needs room for 12 entries: the following 9, plus
@@ -164,39 +205,39 @@ void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
(*outputFunc)(outputStream, "12 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
if (topDict.versionSID != 0) {
- (*outputFunc)(outputStream, "/version (", 10);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/version ", 9);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.noticeSID != 0) {
getString(topDict.noticeSID, buf2, &ok);
- (*outputFunc)(outputStream, "/Notice (", 9);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/Notice ", 8);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.copyrightSID != 0) {
getString(topDict.copyrightSID, buf2, &ok);
- (*outputFunc)(outputStream, "/Copyright (", 12);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/Copyright ", 11);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.fullNameSID != 0) {
getString(topDict.fullNameSID, buf2, &ok);
- (*outputFunc)(outputStream, "/FullName (", 11);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/FullName ", 10);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.familyNameSID != 0) {
getString(topDict.familyNameSID, buf2, &ok);
- (*outputFunc)(outputStream, "/FamilyName (", 13);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/FamilyName ", 12);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.weightSID != 0) {
getString(topDict.weightSID, buf2, &ok);
- (*outputFunc)(outputStream, "/Weight (", 9);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
+ (*outputFunc)(outputStream, "/Weight ", 8);
+ writePSString(buf2, outputFunc, outputStream);
+ (*outputFunc)(outputStream, " readonly def\n", 14);
}
if (topDict.isFixedPitch) {
(*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
@@ -244,13 +285,13 @@ void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
// write the encoding
(*outputFunc)(outputStream, "/Encoding ", 10);
- if (!newEncoding && encoding == fofiType1StandardEncoding) {
+ if (!newEncoding && encoding == (char **)fofiType1StandardEncoding) {
(*outputFunc)(outputStream, "StandardEncoding def\n", 21);
} else {
(*outputFunc)(outputStream, "256 array\n", 10);
(*outputFunc)(outputStream,
"0 1 255 {1 index exch /.notdef put} for\n", 40);
- enc = newEncoding ? newEncoding : encoding;
+ enc = newEncoding ? newEncoding : (const char **)encoding;
for (i = 0; i < 256; ++i) {
if (enc[i]) {
buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
@@ -429,7 +470,7 @@ void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
(*outputFunc)(outputStream, "cleartomark\n", 12);
}
-void FoFiType1C::convertToCIDType0(char *psName,
+void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes,
FoFiOutputFunc outputFunc,
void *outputStream) {
int *cidMap;
@@ -444,18 +485,36 @@ void FoFiType1C::convertToCIDType0(char *psName,
int gid, offset, n, i, j, k;
// compute the CID count and build the CID-to-GID mapping
- nCIDs = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (charset[i] >= nCIDs) {
- nCIDs = charset[i] + 1;
+ if (codeMap) {
+ nCIDs = nCodes;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCodes; ++i) {
+ if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
+ cidMap[i] = codeMap[i];
+ } else {
+ cidMap[i] = -1;
+ }
+ }
+ } else if (topDict.firstOp == 0x0c1e) {
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+ } else {
+ nCIDs = nGlyphs;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = i;
}
- }
- cidMap = (int *)gmallocn(nCIDs, sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- cidMap[i] = -1;
- }
- for (i = 0; i < nGlyphs; ++i) {
- cidMap[charset[i]] = i;
}
// build the charstrings
@@ -467,12 +526,13 @@ void FoFiType1C::convertToCIDType0(char *psName,
ok = gTrue;
getIndexVal(&charStringsIdx, gid, &val, &ok);
if (ok) {
- getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
+ getIndex(privateDicts[fdSelect ? fdSelect[gid] : 0].subrsOffset,
+ &subrIdx, &ok);
if (!ok) {
subrIdx.pos = -1;
}
cvtGlyph(val.pos, val.len, charStrings,
- &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
+ &subrIdx, &privateDicts[fdSelect ? fdSelect[gid] : 0], gTrue);
}
}
}
@@ -497,7 +557,7 @@ void FoFiType1C::convertToCIDType0(char *psName,
(*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
(*outputFunc)(outputStream, "20 dict begin\n", 14);
(*outputFunc)(outputStream, "/CIDFontName /", 14);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
(*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
@@ -506,14 +566,14 @@ void FoFiType1C::convertToCIDType0(char *psName,
getString(topDict.registrySID, buf2, &ok);
if (ok) {
(*outputFunc)(outputStream, " /Registry (", 13);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
(*outputFunc)(outputStream, ") def\n", 6);
}
ok = gTrue;
getString(topDict.orderingSID, buf2, &ok);
if (ok) {
(*outputFunc)(outputStream, " /Ordering (", 13);
- (*outputFunc)(outputStream, buf2, strlen(buf2));
+ (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
(*outputFunc)(outputStream, ") def\n", 6);
}
} else {
@@ -717,7 +777,7 @@ void FoFiType1C::convertToCIDType0(char *psName,
// 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) {
+ if (i+j < nCIDs && cidMap[i+j] >= 0 && fdSelect) {
buf2[0] = (char)fdSelect[cidMap[i+j]];
} else {
buf2[0] = (char)0;
@@ -755,7 +815,7 @@ void FoFiType1C::convertToCIDType0(char *psName,
gfree(cidMap);
}
-void FoFiType1C::convertToType0(char *psName,
+void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes,
FoFiOutputFunc outputFunc,
void *outputStream) {
int *cidMap;
@@ -768,18 +828,36 @@ void FoFiType1C::convertToType0(char *psName,
int fd, i, j, k;
// compute the CID count and build the CID-to-GID mapping
- nCIDs = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (charset[i] >= nCIDs) {
- nCIDs = charset[i] + 1;
+ if (codeMap) {
+ nCIDs = nCodes;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCodes; ++i) {
+ if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
+ cidMap[i] = codeMap[i];
+ } else {
+ cidMap[i] = -1;
+ }
+ }
+ } else if (topDict.firstOp == 0x0c1e) {
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+ } else {
+ nCIDs = nGlyphs;
+ cidMap = (int *)gmallocn(nCIDs, sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = i;
}
- }
- cidMap = (int *)gmallocn(nCIDs, sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- cidMap[i] = -1;
- }
- for (i = 0; i < nGlyphs; ++i) {
- cidMap[charset[i]] = i;
}
// write the descendant Type 1 fonts
@@ -789,17 +867,20 @@ void FoFiType1C::convertToType0(char *psName,
//~ to handle multiple FDs correctly, need to somehow divide the
//~ font up by FD; as a kludge we ignore CID 0, which is .notdef
fd = 0;
- for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
- if (cidMap[i+j] >= 0) {
- fd = fdSelect[cidMap[i+j]];
- break;
+ // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
+ if (fdSelect) {
+ for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ fd = fdSelect[cidMap[i+j]];
+ break;
+ }
}
}
// font dictionary (unencrypted section)
(*outputFunc)(outputStream, "16 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
buf = GString::format("_{0:02x} def\n", i >> 8);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -1031,7 +1112,7 @@ void FoFiType1C::convertToType0(char *psName,
// write the Type 0 parent font
(*outputFunc)(outputStream, "16 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 0 def\n", 16);
if (topDict.hasFontMatrix) {
@@ -1055,7 +1136,7 @@ void FoFiType1C::convertToType0(char *psName,
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
for (i = 0; i < nCIDs; i += 256) {
(*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, psName, (int)strlen(psName));
buf = GString::format("_{0:02x} findfont\n", i >> 8);
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -1066,7 +1147,7 @@ void FoFiType1C::convertToType0(char *psName,
gfree(cidMap);
}
-void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
+void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
int offset, int nBytes,
Type1CIndex *subrIdx,
Type1CPrivateDict *pDict) {
@@ -1792,7 +1873,7 @@ void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
charBuf->append((char *)buf, n);
}
-void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
+void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, const char *s) {
Guchar *p;
Guchar x;
@@ -1836,6 +1917,38 @@ void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
}
}
+void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[80];
+ char *p;
+ int i, c;
+
+ i = 0;
+ buf[i++] = '(';
+ for (p = s; *p; ++p) {
+ c = *p & 0xff;
+ if (c == '(' || c == ')' || c == '\\') {
+ buf[i++] = '\\';
+ buf[i++] = c;
+ } else if (c < 0x20 || c >= 0x80) {
+ buf[i++] = '\\';
+ buf[i++] = '0' + ((c >> 6) & 7);
+ buf[i++] = '0' + ((c >> 3) & 7);
+ buf[i++] = '0' + (c & 7);
+ } else {
+ buf[i++] = c;
+ }
+ if (i >= 64) {
+ buf[i++] = '\\';
+ buf[i++] = '\n';
+ (*outputFunc)(outputStream, buf, i);
+ i = 0;
+ }
+ }
+ buf[i++] = ')';
+ (*outputFunc)(outputStream, buf, i);
+}
+
GBool FoFiType1C::parse() {
Type1CIndex fdIdx;
Type1CIndexVal val;
@@ -1896,6 +2009,7 @@ GBool FoFiType1C::parse() {
// for 8-bit fonts: read the private dict
} else {
+ nFDs = 1;
privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
readPrivateDict(topDict.privateOffset, topDict.privateSize,
&privateDicts[0]);
@@ -2047,6 +2161,8 @@ void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
GBool hasFontMatrix;
hasFontMatrix = gFalse;
+ fontMatrix[0] = fontMatrix[1] = fontMatrix[2] = 0; // make gcc happy
+ fontMatrix[3] = fontMatrix[4] = fontMatrix[5] = 0;
pSize = pOffset = 0;
pos = offset;
nOps = 0;
@@ -2261,10 +2377,10 @@ void FoFiType1C::buildEncoding() {
int pos, c, sid, nLeft, nSups, i, j;
if (topDict.encodingOffset == 0) {
- encoding = fofiType1StandardEncoding;
+ encoding = (char **)fofiType1StandardEncoding;
} else if (topDict.encodingOffset == 1) {
- encoding = fofiType1ExpertEncoding;
+ encoding = (char **)fofiType1ExpertEncoding;
} else {
encoding = (char **)gmallocn(256, sizeof(char *));
@@ -2584,7 +2700,9 @@ char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
Type1CIndexVal val;
int n;
- if (sid < 391) {
+ if (sid < 0) {
+ buf[0] = '\0';
+ } else if (sid < 391) {
strcpy(buf, fofiType1CStdStrings[sid]);
} else {
sid -= 391;
diff --git a/fofi/FoFiType1C.h b/fofi/FoFiType1C.h
index eec2755..0c5b4fb 100644
--- a/fofi/FoFiType1C.h
+++ b/fofi/FoFiType1C.h
@@ -149,9 +149,16 @@ public:
// be NULL). This is only useful with 8-bit fonts.
char **getEncoding();
+ // Get the glyph names.
+ int getNumGlyphs() { return nGlyphs; }
+ GString *getGlyphName(int gid);
+
// Return the mapping from CIDs to GIDs, and return the number of
// CIDs in *<nCIDs>. This is only useful for CID fonts.
- Gushort *getCIDToGIDMap(int *nCIDs);
+ int *getCIDToGIDMap(int *nCIDs);
+
+ // Return the font matrix as an array of six numbers.
+ void getFontMatrix(double *mat);
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
@@ -159,25 +166,36 @@ public:
// 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.
- void convertToType1(char *psName, char **newEncoding, GBool ascii,
+ void convertToType1(char *psName, const char **newEncoding, GBool ascii,
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.
- void convertToCIDType0(char *psName,
+ // name. There are three cases for the CID-to-GID mapping:
+ // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
+ // (2) if <codeMap> is NULL and this is a CID CFF font, then the
+ // font's internal CID-to-GID mapping is used
+ // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
+ // the identity CID-to-GID mapping is used
+ void convertToCIDType0(char *psName, int *codeMap, int nCodes,
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.
- void convertToType0(char *psName,
+ // PostScript font name. There are three cases for the CID-to-GID
+ // mapping:
+ // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
+ // (2) if <codeMap> is NULL and this is a CID CFF font, then the
+ // font's internal CID-to-GID mapping is used
+ // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
+ // the identity CID-to-GID mapping is used
+ void convertToType0(char *psName, int *codeMap, int nCodes,
FoFiOutputFunc outputFunc, void *outputStream);
private:
FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
- void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
+ void eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
int offset, int nBytes,
Type1CIndex *subrIdx,
Type1CPrivateDict *pDict);
@@ -187,8 +205,9 @@ private:
void cvtGlyphWidth(GBool useOp, GString *charBuf,
Type1CPrivateDict *pDict);
void cvtNum(double x, GBool isFP, GString *charBuf);
- void eexecWrite(Type1CEexecBuf *eb, char *s);
+ void eexecWrite(Type1CEexecBuf *eb, const char *s);
void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n);
+ void writePSString(char *s, FoFiOutputFunc outputFunc, void *outputStream);
GBool parse();
void readTopDict();
void readFD(int offset, int length, Type1CPrivateDict *pDict);
diff --git a/fofi/Makefile.in b/fofi/Makefile.in
index d0ac7a7..f4f5d00 100644
--- a/fofi/Makefile.in
+++ b/fofi/Makefile.in
@@ -34,6 +34,7 @@ LIBPREFIX = @LIBPREFIX@
CXX_SRC = \
$(srcdir)/FoFiBase.cc \
$(srcdir)/FoFiEncodings.cc \
+ $(srcdir)/FoFiIdentifier.cc \
$(srcdir)/FoFiTrueType.cc \
$(srcdir)/FoFiType1.cc \
$(srcdir)/FoFiType1C.cc
@@ -47,6 +48,7 @@ all: $(LIBPREFIX)fofi.a
FOFI_OBJS = \
FoFiBase.o \
FoFiEncodings.o \
+ FoFiIdentifier.o \
FoFiTrueType.o \
FoFiType1.o \
FoFiType1C.o
diff --git a/goo/FixedPoint.cc b/goo/FixedPoint.cc
index 47c2834..34661ad 100644
--- a/goo/FixedPoint.cc
+++ b/goo/FixedPoint.cc
@@ -80,28 +80,32 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
}
int FixedPoint::mul(int x, int y) {
-#if 1 //~tmp
- return ((FixPtInt64)x * y) >> fixptShift;
-#else
- int ah0, ah, bh, al, bl;
- ah0 = x & fixptMaskH;
- ah = x >> fixptShift;
- al = x - ah0;
- bh = y >> fixptShift;
- bl = y - (bh << fixptShift);
- return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift);
-#endif
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x * y) >> fixptShift;
+ if (z > 0x7fffffffLL) {
+ return 0x7fffffff;
+ } else if (z < -0x80000000LL) {
+ return 0x80000000;
+ } else {
+ return (int)z;
+ }
}
int FixedPoint::div(int x, int y) {
-#if 1 //~tmp
- return ((FixPtInt64)x << fixptShift) / y;
-#else
-#endif
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x << fixptShift) / y;
+ if (z > 0x7fffffffLL) {
+ return 0x7fffffff;
+ } else if (z < -0x80000000LL) {
+ return 0x80000000;
+ } else {
+ return (int)z;
+ }
}
GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
-#if 1 //~tmp
FixPtInt64 z;
z = ((FixPtInt64)x.val << fixptShift) / y.val;
@@ -111,8 +115,19 @@ GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
}
result->val = z;
return gTrue;
-#else
-#endif
+}
+
+GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
+ FixedPoint m21, FixedPoint m22,
+ FixedPoint epsilon) {
+ FixPtInt64 det, e;
+
+ det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
+ - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
+ e = (FixPtInt64)epsilon.val << fixptShift;
+ // NB: this comparison has to be >= not > because epsilon can be
+ // truncated to zero as a fixed point value.
+ return det >= e || det <= -e;
}
#endif // USE_FIXEDPOINT
diff --git a/goo/FixedPoint.h b/goo/FixedPoint.h
index abcb212..f9cdd4e 100644
--- a/goo/FixedPoint.h
+++ b/goo/FixedPoint.h
@@ -45,7 +45,7 @@ public:
operator int()
{ return val >> fixptShift; }
- int getRaw() { return val; }
+ int get16Dot16() { return val; }
FixedPoint operator =(FixedPoint x) { val = x.val; return *this; }
@@ -132,6 +132,11 @@ public:
static int round(FixedPoint x)
{ return (x.val + (1 << (fixptShift - 1))) >> fixptShift; }
+ // Computes (x+y)/2 avoiding overflow and LSbit accuracy issues.
+ static FixedPoint avg(FixedPoint x, FixedPoint y)
+ { return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); }
+
+
static FixedPoint sqrt(FixedPoint x);
static FixedPoint pow(FixedPoint x, FixedPoint y);
@@ -140,6 +145,12 @@ public:
// overflow.
static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
+ // Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case
+ // where the multiplications overflow.
+ static GBool checkDet(FixedPoint m11, FixedPoint m12,
+ FixedPoint m21, FixedPoint m22,
+ FixedPoint epsilon);
+
private:
static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
@@ -147,7 +158,7 @@ private:
static int mul(int x, int y);
static int div(int x, int y);
- int val; // 16.16 fixed point
+ int val; // fixed point: (n-fixptShift).(fixptShift)
};
#endif // USE_FIXEDPOINT
diff --git a/goo/GHash.cc b/goo/GHash.cc
index b51a764..32e85b4 100644
--- a/goo/GHash.cc
+++ b/goo/GHash.cc
@@ -107,7 +107,9 @@ void GHash::replace(GString *key, void *val) {
if ((p = find(key, &h))) {
p->val.p = val;
- delete key;
+ if (deleteKeys) {
+ delete key;
+ }
} else {
add(key, val);
}
@@ -119,7 +121,9 @@ void GHash::replace(GString *key, int val) {
if ((p = find(key, &h))) {
p->val.i = val;
- delete key;
+ if (deleteKeys) {
+ delete key;
+ }
} else {
add(key, val);
}
@@ -145,7 +149,7 @@ int GHash::lookupInt(GString *key) {
return p->val.i;
}
-void *GHash::lookup(char *key) {
+void *GHash::lookup(const char *key) {
GHashBucket *p;
int h;
@@ -155,7 +159,7 @@ void *GHash::lookup(char *key) {
return p->val.p;
}
-int GHash::lookupInt(char *key) {
+int GHash::lookupInt(const char *key) {
GHashBucket *p;
int h;
@@ -211,7 +215,7 @@ int GHash::removeInt(GString *key) {
return val;
}
-void *GHash::remove(char *key) {
+void *GHash::remove(const char *key) {
GHashBucket *p;
GHashBucket **q;
void *val;
@@ -234,7 +238,7 @@ void *GHash::remove(char *key) {
return val;
}
-int GHash::removeInt(char *key) {
+int GHash::removeInt(const char *key) {
GHashBucket *p;
GHashBucket **q;
int val;
@@ -344,7 +348,7 @@ GHashBucket *GHash::find(GString *key, int *h) {
return NULL;
}
-GHashBucket *GHash::find(char *key, int *h) {
+GHashBucket *GHash::find(const char *key, int *h) {
GHashBucket *p;
*h = hash(key);
@@ -357,7 +361,7 @@ GHashBucket *GHash::find(char *key, int *h) {
}
int GHash::hash(GString *key) {
- char *p;
+ const char *p;
unsigned int h;
int i;
@@ -368,8 +372,8 @@ int GHash::hash(GString *key) {
return (int)(h % size);
}
-int GHash::hash(char *key) {
- char *p;
+int GHash::hash(const char *key) {
+ const char *p;
unsigned int h;
h = 0;
diff --git a/goo/GHash.h b/goo/GHash.h
index 31aba93..179753a 100644
--- a/goo/GHash.h
+++ b/goo/GHash.h
@@ -34,12 +34,12 @@ public:
void replace(GString *key, int val);
void *lookup(GString *key);
int lookupInt(GString *key);
- void *lookup(char *key);
- int lookupInt(char *key);
+ void *lookup(const char *key);
+ int lookupInt(const char *key);
void *remove(GString *key);
int removeInt(GString *key);
- void *remove(char *key);
- int removeInt(char *key);
+ void *remove(const char *key);
+ int removeInt(const char *key);
int getLength() { return len; }
void startIter(GHashIter **iter);
GBool getNext(GHashIter **iter, GString **key, void **val);
@@ -50,9 +50,9 @@ private:
void expand();
GHashBucket *find(GString *key, int *h);
- GHashBucket *find(char *key, int *h);
+ GHashBucket *find(const char *key, int *h);
int hash(GString *key);
- int hash(char *key);
+ int hash(const char *key);
GBool deleteKeys; // set if key strings should be deleted
int size; // number of buckets
diff --git a/goo/GList.cc b/goo/GList.cc
index fb5fd62..5d9cba3 100644
--- a/goo/GList.cc
+++ b/goo/GList.cc
@@ -29,7 +29,7 @@ GList::GList() {
}
GList::GList(int sizeA) {
- size = sizeA;
+ size = sizeA ? sizeA : 8;
data = (void **)gmallocn(size, sizeof(void*));
length = 0;
inc = 0;
@@ -39,6 +39,16 @@ GList::~GList() {
gfree(data);
}
+GList *GList::copy() {
+ GList *ret;
+
+ ret = new GList(length);
+ ret->length = length;
+ memcpy(ret->data, data, length * sizeof(void *));
+ ret->inc = inc;
+ return ret;
+}
+
void GList::append(void *p) {
if (length >= size) {
expand();
@@ -61,6 +71,9 @@ void GList::insert(int i, void *p) {
if (length >= size) {
expand();
}
+ if (i < 0) {
+ i = 0;
+ }
if (i < length) {
memmove(data+i+1, data+i, (length - i) * sizeof(void *));
}
@@ -86,6 +99,18 @@ void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) {
qsort(data, length, sizeof(void *), cmp);
}
+void GList::reverse() {
+ void *t;
+ int n, i;
+
+ n = length / 2;
+ for (i = 0; i < n; ++i) {
+ t = data[i];
+ data[i] = data[length - 1 - i];
+ data[length - 1 - i] = t;
+ }
+}
+
void GList::expand() {
size += (inc > 0) ? inc : size;
data = (void **)greallocn(data, size, sizeof(void*));
diff --git a/goo/GList.h b/goo/GList.h
index e4d8ff8..0050437 100644
--- a/goo/GList.h
+++ b/goo/GList.h
@@ -38,12 +38,19 @@ public:
// Get the number of elements.
int getLength() { return length; }
+ // Returns a (shallow) copy of this list.
+ GList *copy();
+
//----- ordered list support
// Return the <i>th element.
// Assumes 0 <= i < length.
void *get(int i) { return data[i]; }
+ // Replace the <i>th element.
+ // Assumes 0 <= i < length.
+ void put(int i, void *p) { data[i] = p; }
+
// Append an element to the end of the list.
void append(void *p);
@@ -63,6 +70,9 @@ public:
// be double-dereferenced.
void sort(int (*cmp)(const void *ptr1, const void *ptr2));
+ // Reverse the list.
+ void reverse();
+
//----- control
// Set allocation increment to <inc>. If inc > 0, that many
diff --git a/goo/GString.cc b/goo/GString.cc
index e21fd3e..ea0b3ca 100644
--- a/goo/GString.cc
+++ b/goo/GString.cc
@@ -29,6 +29,12 @@ union GStringFormatArg {
Guint ui;
long l;
Gulong ul;
+#ifdef LLONG_MAX
+ long long ll;
+#endif
+#ifdef ULLONG_MAX
+ unsigned long long ull;
+#endif
double f;
char c;
char *s;
@@ -52,6 +58,18 @@ enum GStringFormatType {
fmtULongHex,
fmtULongOctal,
fmtULongBinary,
+#ifdef LLONG_MAX
+ fmtLongLongDecimal,
+ fmtLongLongHex,
+ fmtLongLongOctal,
+ fmtLongLongBinary,
+#endif
+#ifdef ULLONG_MAX
+ fmtULongLongDecimal,
+ fmtULongLongHex,
+ fmtULongLongOctal,
+ fmtULongLongBinary,
+#endif
fmtDouble,
fmtDoubleTrim,
fmtChar,
@@ -60,9 +78,15 @@ enum GStringFormatType {
fmtSpace
};
-static char *formatStrings[] = {
+static const char *formatStrings[] = {
"d", "x", "o", "b", "ud", "ux", "uo", "ub",
"ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
+#ifdef LLONG_MAX
+ "lld", "llx", "llo", "llb",
+#endif
+#ifdef ULLONG_MAX
+ "ulld", "ullx", "ullo", "ullb",
+#endif
"f", "g",
"c",
"s",
@@ -105,7 +129,7 @@ GString::GString() {
}
GString::GString(const char *sA) {
- int n = strlen(sA);
+ int n = (int)strlen(sA);
s = NULL;
resize(length = n);
@@ -151,7 +175,7 @@ GString *GString::fromInt(int x) {
return new GString(p, len);
}
-GString *GString::format(char *fmt, ...) {
+GString *GString::format(const char *fmt, ...) {
va_list argList;
GString *s;
@@ -162,7 +186,7 @@ GString *GString::format(char *fmt, ...) {
return s;
}
-GString *GString::formatv(char *fmt, va_list argList) {
+GString *GString::formatv(const char *fmt, va_list argList) {
GString *s;
s = new GString();
@@ -197,7 +221,7 @@ GString *GString::append(GString *str) {
}
GString *GString::append(const char *str) {
- int n = strlen(str);
+ int n = (int)strlen(str);
resize(length + n);
memcpy(s + length, str, n + 1);
@@ -213,7 +237,7 @@ GString *GString::append(const char *str, int lengthA) {
return this;
}
-GString *GString::appendf(char *fmt, ...) {
+GString *GString::appendf(const char *fmt, ...) {
va_list argList;
va_start(argList, fmt);
@@ -222,7 +246,7 @@ GString *GString::appendf(char *fmt, ...) {
return this;
}
-GString *GString::appendfv(char *fmt, va_list argList) {
+GString *GString::appendfv(const char *fmt, va_list argList) {
GStringFormatArg *args;
int argsLen, argsSize;
GStringFormatArg arg;
@@ -231,7 +255,8 @@ GString *GString::appendfv(char *fmt, va_list argList) {
GStringFormatType ft;
char buf[65];
int len, i;
- char *p0, *p1, *str;
+ const char *p0, *p1;
+ char *str;
argsLen = 0;
argsSize = 8;
@@ -269,6 +294,9 @@ GString *GString::appendfv(char *fmt, va_list argList) {
for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
width = 10 * width + (*p0 - '0');
}
+ if (width < 0) {
+ width = 0;
+ }
if (*p0 == '.') {
++p0;
prec = 0;
@@ -330,6 +358,22 @@ GString *GString::appendfv(char *fmt, va_list argList) {
case fmtULongBinary:
args[argsLen].ul = va_arg(argList, Gulong);
break;
+#ifdef LLONG_MAX
+ case fmtLongLongDecimal:
+ case fmtLongLongHex:
+ case fmtLongLongOctal:
+ case fmtLongLongBinary:
+ args[argsLen].ll = va_arg(argList, long long);
+ break;
+#endif
+#ifdef ULLONG_MAX
+ case fmtULongLongDecimal:
+ case fmtULongLongHex:
+ case fmtULongLongOctal:
+ case fmtULongLongBinary:
+ args[argsLen].ull = va_arg(argList, unsigned long long);
+ break;
+#endif
case fmtDouble:
case fmtDoubleTrim:
args[argsLen].f = va_arg(argList, double);
@@ -402,6 +446,38 @@ GString *GString::appendfv(char *fmt, va_list argList) {
case fmtULongBinary:
formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
break;
+#ifdef LLONG_MAX
+ case fmtLongLongDecimal:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtLongLongHex:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtLongLongOctal:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtLongLongBinary:
+ formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+#endif
+#ifdef ULLONG_MAX
+ case fmtULongLongDecimal:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtULongLongHex:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtULongLongOctal:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 8,
+ &str, &len);
+ break;
+ case fmtULongLongBinary:
+ formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 2,
+ &str, &len);
+ break;
+#endif
case fmtDouble:
formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
break;
@@ -416,7 +492,7 @@ GString *GString::appendfv(char *fmt, va_list argList) {
break;
case fmtString:
str = arg.s;
- len = strlen(str);
+ len = (int)strlen(str);
reverseAlign = !reverseAlign;
break;
case fmtGString:
@@ -454,7 +530,7 @@ GString *GString::appendfv(char *fmt, va_list argList) {
} else {
for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
- append(p0, p1 - p0);
+ append(p0, (int)(p1 - p0));
p0 = p1;
}
}
@@ -463,9 +539,15 @@ GString *GString::appendfv(char *fmt, va_list argList) {
return this;
}
+#ifdef LLONG_MAX
+void GString::formatInt(long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len) {
+#else
void GString::formatInt(long x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len) {
+#endif
static char vals[17] = "0123456789abcdef";
GBool neg;
int start, i, j;
@@ -495,9 +577,15 @@ void GString::formatInt(long x, char *buf, int bufSize,
*len = bufSize - i;
}
+#ifdef ULLONG_MAX
+void GString::formatUInt(unsigned long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len) {
+#else
void GString::formatUInt(Gulong x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len) {
+#endif
static char vals[17] = "0123456789abcdef";
int i, j;
@@ -528,7 +616,7 @@ void GString::formatDouble(double x, char *buf, int bufSize, int prec,
if ((neg = x < 0)) {
x = -x;
}
- x = floor(x * pow(10, prec) + 0.5);
+ x = floor(x * pow(10.0, prec) + 0.5);
i = bufSize;
started = !trim;
for (j = 0; j < prec && i > 1; ++j) {
@@ -582,7 +670,7 @@ GString *GString::insert(int i, GString *str) {
}
GString *GString::insert(int i, const char *str) {
- int n = strlen(str);
+ int n = (int)strlen(str);
int j;
resize(length + n);
@@ -607,7 +695,7 @@ GString *GString::insert(int i, const char *str, int lengthA) {
GString *GString::del(int i, int n) {
int j;
- if (n > 0) {
+ if (i >= 0 && n > 0 && i + n > 0) {
if (i + n > length) {
n = length - i;
}
diff --git a/goo/GString.h b/goo/GString.h
index dd22e2d..611efda 100644
--- a/goo/GString.h
+++ b/goo/GString.h
@@ -17,6 +17,7 @@
#pragma interface
#endif
+#include <limits.h> // for LLONG_MAX and ULLONG_MAX
#include <stdarg.h>
#include "gtypes.h"
@@ -61,14 +62,16 @@ public:
// 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
+ // lld, llx, llo, llb, ulld, ullx, ullo, ullb
+ // -- long long, unsigned long 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);
+ static GString *format(const char *fmt, ...);
+ static GString *formatv(const char *fmt, va_list argList);
// Destructor.
~GString();
@@ -95,8 +98,8 @@ public:
GString *append(const char *str, int lengthA);
// Append a formatted string.
- GString *appendf(char *fmt, ...);
- GString *appendfv(char *fmt, va_list argList);
+ GString *appendf(const char *fmt, ...);
+ GString *appendfv(const char *fmt, va_list argList);
// Insert a character or string.
GString *insert(int i, char c);
@@ -123,12 +126,24 @@ private:
char *s;
void resize(int length1);
+#ifdef LLONG_MAX
+ static void formatInt(long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len);
+#else
static void formatInt(long x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len);
+#endif
+#ifdef ULLONG_MAX
+ static void formatUInt(unsigned long long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len);
+#else
static void formatUInt(Gulong x, char *buf, int bufSize,
GBool zeroFill, int width, int base,
char **p, int *len);
+#endif
static void formatDouble(double x, char *buf, int bufSize, int prec,
GBool trim, char **p, int *len);
};
diff --git a/goo/gfile.cc b/goo/gfile.cc
index 54a7be3..93d0941 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -20,6 +20,7 @@
# include <sys/stat.h>
# include <fcntl.h>
# endif
+# include <time.h>
# include <limits.h>
# include <string.h>
# if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
@@ -104,7 +105,7 @@ GString *getCurrentDir() {
return new GString();
}
-GString *appendToPath(GString *path, char *fileName) {
+GString *appendToPath(GString *path, const char *fileName) {
#if defined(VMS)
//---------- VMS ----------
//~ this should handle everything necessary for file
@@ -286,11 +287,11 @@ GString *grabPath(char *fileName) {
char *p;
if ((p = strrchr(fileName, '/')))
- return new GString(fileName, p - fileName);
+ return new GString(fileName, (int)(p - fileName));
if ((p = strrchr(fileName, '\\')))
- return new GString(fileName, p - fileName);
+ return new GString(fileName, (int)(p - fileName));
if ((p = strrchr(fileName, ':')))
- return new GString(fileName, p + 1 - fileName);
+ return new GString(fileName, (int)(p + 1 - fileName));
return new GString();
#elif defined(ACORN)
@@ -439,12 +440,11 @@ time_t getModTime(char *fileName) {
#endif
}
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
+GBool openTempFile(GString **name, FILE **f, const char *mode, char *ext) {
#if defined(WIN32)
//---------- Win32 ----------
char *tempDir;
GString *s, *s2;
- char buf[32];
FILE *f2;
int t, i;
@@ -457,11 +457,11 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
} else {
s = new GString();
}
- s->append("x");
+ s->appendf("x_{0:d}_{1:d}_",
+ (int)GetCurrentProcessId(), (int)GetCurrentThreadId());
t = (int)time(NULL);
for (i = 0; i < 1000; ++i) {
- sprintf(buf, "%d", t + i);
- s2 = s->copy()->append(buf);
+ s2 = s->copy()->appendf("{0:d}", t + i);
if (ext) {
s2->append(ext);
}
@@ -498,6 +498,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
}
if (!(*f = fopen((*name)->getCString(), mode))) {
delete (*name);
+ *name = NULL;
return gFalse;
}
return gTrue;
@@ -542,6 +543,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
}
if (fd < 0 || !(*f = fdopen(fd, mode))) {
delete *name;
+ *name = NULL;
return gFalse;
}
return gTrue;
@@ -556,6 +558,107 @@ GBool executeCommand(char *cmd) {
#endif
}
+#ifdef WIN32
+GString *fileNameToUTF8(char *path) {
+ GString *s;
+ char *p;
+
+ s = new GString();
+ for (p = path; *p; ++p) {
+ if (*p & 0x80) {
+ s->append((char)(0xc0 | ((*p >> 6) & 0x03)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ } else {
+ s->append(*p);
+ }
+ }
+ return s;
+}
+
+GString *fileNameToUTF8(wchar_t *path) {
+ GString *s;
+ wchar_t *p;
+
+ s = new GString();
+ for (p = path; *p; ++p) {
+ if (*p < 0x80) {
+ s->append((char)*p);
+ } else if (*p < 0x800) {
+ s->append((char)(0xc0 | ((*p >> 6) & 0x1f)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ } else {
+ s->append((char)(0xe0 | ((*p >> 12) & 0x0f)));
+ s->append((char)(0x80 | ((*p >> 6) & 0x3f)));
+ s->append((char)(0x80 | (*p & 0x3f)));
+ }
+ }
+ return s;
+}
+#endif
+
+FILE *openFile(const char *path, const char *mode) {
+#ifdef WIN32
+ OSVERSIONINFO version;
+ wchar_t wPath[_MAX_PATH + 1];
+ char nPath[_MAX_PATH + 1];
+ wchar_t wMode[8];
+ const char *p;
+ int i;
+
+ // NB: _wfopen is only available in NT
+ version.dwOSVersionInfoSize = sizeof(version);
+ GetVersionEx(&version);
+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
+ if ((p[0] & 0xe0) == 0xc0 &&
+ p[1] && (p[1] & 0xc0) == 0x80) {
+ wPath[i] = (wchar_t)(((p[0] & 0x1f) << 6) |
+ (p[1] & 0x3f));
+ p += 2;
+ } else if ((p[0] & 0xf0) == 0xe0 &&
+ p[1] && (p[1] & 0xc0) == 0x80 &&
+ p[2] && (p[2] & 0xc0) == 0x80) {
+ wPath[i] = (wchar_t)(((p[0] & 0x0f) << 12) |
+ ((p[1] & 0x3f) << 6) |
+ (p[2] & 0x3f));
+ p += 3;
+ } else {
+ wPath[i] = (wchar_t)(p[0] & 0xff);
+ p += 1;
+ }
+ }
+ wPath[i] = (wchar_t)0;
+ for (i = 0; mode[i] && i < sizeof(mode) - 1; ++i) {
+ wMode[i] = (wchar_t)(mode[i] & 0xff);
+ }
+ wMode[i] = (wchar_t)0;
+ return _wfopen(wPath, wMode);
+ } else {
+ for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
+ if ((p[0] & 0xe0) == 0xc0 &&
+ p[1] && (p[1] & 0xc0) == 0x80) {
+ nPath[i] = (char)(((p[0] & 0x1f) << 6) |
+ (p[1] & 0x3f));
+ p += 2;
+ } else if ((p[0] & 0xf0) == 0xe0 &&
+ p[1] && (p[1] & 0xc0) == 0x80 &&
+ p[2] && (p[2] & 0xc0) == 0x80) {
+ nPath[i] = (char)(((p[1] & 0x3f) << 6) |
+ (p[2] & 0x3f));
+ p += 3;
+ } else {
+ nPath[i] = p[0];
+ p += 1;
+ }
+ }
+ nPath[i] = '\0';
+ return fopen(nPath, mode);
+ }
+#else
+ return fopen(path, mode);
+#endif
+}
+
char *getLine(char *buf, int size, FILE *f) {
int c, i;
diff --git a/goo/gfile.h b/goo/gfile.h
index 82f1d7a..4f8c65f 100644
--- a/goo/gfile.h
+++ b/goo/gfile.h
@@ -60,7 +60,7 @@ extern GString *getCurrentDir();
// Append a file name to a path string. <path> may be an empty
// string, denoting the current directory). Returns <path>.
-extern GString *appendToPath(GString *path, char *fileName);
+extern GString *appendToPath(GString *path, const char *fileName);
// Grab the path from the front of the file name. If there is no
// directory component in <fileName>, returns an empty string.
@@ -83,11 +83,25 @@ 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.
-extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
+extern GBool openTempFile(GString **name, FILE **f,
+ const char *mode, char *ext);
// Execute <command>. Returns true on success.
extern GBool executeCommand(char *cmd);
+#ifdef WIN32
+// Convert a file name from Latin-1 to UTF-8.
+extern GString *fileNameToUTF8(char *path);
+
+// Convert a file name from UCS-2 to UTF-8.
+extern GString *fileNameToUTF8(wchar_t *path);
+#endif
+
+// Open a file. On Windows, this converts the path from UTF-8 to
+// UCS-2 and calls _wfopen (if available). On other OSes, this simply
+// calls fopen.
+extern FILE *openFile(const char *path, const char *mode);
+
// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
// conventions.
extern char *getLine(char *buf, int size, FILE *f);
diff --git a/goo/gmem.cc b/goo/gmem.cc
index 6b13b38..af85dd0 100644
--- a/goo/gmem.cc
+++ b/goo/gmem.cc
@@ -55,7 +55,15 @@ void *gmalloc(int size) GMEM_EXCEP {
void *data;
unsigned long *trl, *p;
- if (size <= 0) {
+ if (size < 0) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
+ fprintf(stderr, "Invalid memory allocation size\n");
+ exit(1);
+#endif
+ }
+ if (size == 0) {
return NULL;
}
size1 = gMemDataSize(size);
@@ -91,7 +99,15 @@ void *gmalloc(int size) GMEM_EXCEP {
#else
void *p;
- if (size <= 0) {
+ if (size < 0) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
+ fprintf(stderr, "Invalid memory allocation size\n");
+ exit(1);
+#endif
+ }
+ if (size == 0) {
return NULL;
}
if (!(p = malloc(size))) {
@@ -112,7 +128,15 @@ void *grealloc(void *p, int size) GMEM_EXCEP {
void *q;
int oldSize;
- if (size <= 0) {
+ if (size < 0) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
+ fprintf(stderr, "Invalid memory allocation size\n");
+ exit(1);
+#endif
+ }
+ if (size == 0) {
if (p) {
gfree(p);
}
@@ -131,7 +155,15 @@ void *grealloc(void *p, int size) GMEM_EXCEP {
#else
void *q;
- if (size <= 0) {
+ if (size < 0) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
+ fprintf(stderr, "Invalid memory allocation size\n");
+ exit(1);
+#endif
+ }
+ if (size == 0) {
if (p) {
free(p);
}
@@ -255,10 +287,10 @@ void gMemReport(FILE *f) {
}
#endif
-char *copyString(char *s) {
+char *copyString(const char *s) {
char *s1;
- s1 = (char *)gmalloc(strlen(s) + 1);
+ s1 = (char *)gmalloc((int)strlen(s) + 1);
strcpy(s1, s);
return s1;
}
diff --git a/goo/gmem.h b/goo/gmem.h
index da34736..de32453 100644
--- a/goo/gmem.h
+++ b/goo/gmem.h
@@ -70,7 +70,7 @@ extern void gMemReport(FILE *f);
/*
* Allocate memory and copy a string into it.
*/
-extern char *copyString(char *s);
+extern char *copyString(const char *s);
#ifdef __cplusplus
}
diff --git a/goo/parseargs.c b/goo/parseargs.c
index f77cc85..fdefa6c 100644
--- a/goo/parseargs.c
+++ b/goo/parseargs.c
@@ -39,14 +39,14 @@ GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) {
return ok;
}
-void printUsage(char *program, char *otherArgs, ArgDesc *args) {
+void printUsage(const char *program, const char *otherArgs, ArgDesc *args) {
ArgDesc *arg;
char *typ;
int w, w1;
w = 0;
for (arg = args; arg->arg; ++arg) {
- if ((w1 = strlen(arg->arg)) > w)
+ if ((w1 = (int)strlen(arg->arg)) > w)
w = w1;
}
@@ -57,7 +57,7 @@ void printUsage(char *program, char *otherArgs, ArgDesc *args) {
for (arg = args; arg->arg; ++arg) {
fprintf(stderr, " %s", arg->arg);
- w1 = 9 + w - strlen(arg->arg);
+ w1 = 9 + w - (int)strlen(arg->arg);
switch (arg->kind) {
case argInt:
case argIntDummy:
diff --git a/goo/parseargs.h b/goo/parseargs.h
index 0d163b9..b4daa3f 100644
--- a/goo/parseargs.h
+++ b/goo/parseargs.h
@@ -39,11 +39,11 @@ typedef enum {
* Argument descriptor.
*/
typedef struct {
- char *arg; /* the command line switch */
+ const char *arg; /* the command line switch */
ArgKind kind; /* kind of arg */
void *val; /* place to store value */
int size; /* for argString: size of string */
- char *usage; /* usage string */
+ const char *usage; /* usage string */
} ArgDesc;
/*
@@ -56,7 +56,8 @@ extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]);
/*
* Print usage message, based on arg descriptor list.
*/
-extern void printUsage(char *program, char *otherArgs, ArgDesc *args);
+extern void printUsage(const char *program, const char *otherArgs,
+ ArgDesc *args);
/*
* Check if a string is a valid integer or floating point number.
diff --git a/ms_make.bat b/ms_make.bat
index 6bbaf35..c4b01a4 100644
--- a/ms_make.bat
+++ b/ms_make.bat
@@ -1,5 +1,5 @@
set CC=cl
-set CFLAGS=/DWIN32 /I.. /I..\goo /I..\fofi /O2 /nologo
+set CFLAGS=/DWIN32 /I.. /I..\goo /I..\fofi /I..\splash /O2 /nologo
set CXX=cl
set CXXFLAGS=%CFLAGS% /TP
set LIBPROG=lib
@@ -20,10 +20,11 @@ cd goo
cd ..\fofi
%CXX% %CXXFLAGS% /c FoFiBase.cc
%CXX% %CXXFLAGS% /c FoFiEncodings.cc
+%CXX% %CXXFLAGS% /c FoFiIdentifier.cc
%CXX% %CXXFLAGS% /c FoFiTrueType.cc
%CXX% %CXXFLAGS% /c FoFiType1.cc
%CXX% %CXXFLAGS% /c FoFiType1C.cc
-%LIBPROG% /nologo /out:fofi.lib FoFiBase.obj FoFiEncodings.obj FoFiTrueType.obj FoFiType1.obj FoFiType1C.obj
+%LIBPROG% /nologo /out:fofi.lib FoFiBase.obj FoFiEncodings.obj FoFiIdentifier.obj FoFiTrueType.obj FoFiType1.obj FoFiType1C.obj
cd ..\xpdf
%CXX% %CXXFLAGS% /c Annot.cc
@@ -50,6 +51,7 @@ cd ..\xpdf
%CXX% %CXXFLAGS% /c Link.cc
%CXX% %CXXFLAGS% /c NameToCharCode.cc
%CXX% %CXXFLAGS% /c Object.cc
+%CXX% %CXXFLAGS% /c OptionalContent.cc
%CXX% %CXXFLAGS% /c Outline.cc
%CXX% %CXXFLAGS% /c OutputDev.cc
%CXX% %CXXFLAGS% /c PDFDoc.cc
@@ -58,6 +60,7 @@ cd ..\xpdf
%CXX% %CXXFLAGS% /c PSTokenizer.cc
%CXX% %CXXFLAGS% /c Page.cc
%CXX% %CXXFLAGS% /c Parser.cc
+%CXX% %CXXFLAGS% /c PreScanOutputDev.cc
%CXX% %CXXFLAGS% /c SecurityHandler.cc
%CXX% %CXXFLAGS% /c Stream.cc
%CXX% %CXXFLAGS% /c TextOutputDev.cc
@@ -68,24 +71,30 @@ cd ..\xpdf
%CXX% %CXXFLAGS% /c pdftotext.cc
%CXX% %CXXFLAGS% /c pdfinfo.cc
%CXX% %CXXFLAGS% /c pdffonts.cc
+%CXX% %CXXFLAGS% /c pdfdetach.cc
%CXX% %CXXFLAGS% /c pdfimages.cc
-%CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+rem --- Comment out this line, and uncomment the other pdftops build line
+rem (see below) to build pdftops with the Splash rasterizer.
+rem You'll also need to define HAVE_SPLASH in aconf-win32.h.
+%CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj PreScanOutputDev.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-%CXX% %LINKFLAGS% /Fepdftotext.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextOutputDev.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftotext.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+%CXX% %LINKFLAGS% /Fepdftotext.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextOutputDev.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftotext.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-%CXX% %LINKFLAGS% /Fepdfinfo.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfinfo.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+%CXX% %LINKFLAGS% /Fepdfinfo.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfinfo.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-%CXX% %LINKFLAGS% /Fepdffonts.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdffonts.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+%CXX% %LINKFLAGS% /Fepdffonts.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdffonts.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-%CXX% %LINKFLAGS% /Fepdfimages.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj ImageOutputDev.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfimages.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+%CXX% %LINKFLAGS% /Fepdfdetach.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfdetach.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdfimages.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj ImageOutputDev.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfimages.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
cd ..
rem --- This part will only work if you have FreeType installed ---
-set FT2DIR=..\freetype-2.3.1
-set CXXFLAGS=%CXXFLAGS% /I..\splash /I%FT2DIR%\include
+set FT2DIR=..\freetype-2.4.6
+set CXXFLAGS=%CXXFLAGS% /I%FT2DIR%\include
cd splash
%CXX% %CXXFLAGS% /c Splash.cc
@@ -113,6 +122,11 @@ cd ..\xpdf
%CXX% %CXXFLAGS% /c SplashOutputDev.cc
%CXX% %CXXFLAGS% /c pdftoppm.cc
-%CXX% %LINKFLAGS% /Fepdftoppm.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftoppm.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+%CXX% %LINKFLAGS% /Fepdftoppm.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftoppm.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+rem --- Uncomment this line, and comment out the other pdftops build
+rem line (see above) to build pdftops with the Splash rasterizer.
+rem You'll also need to define HAVE_SPLASH in aconf-win32.h.
+rem %CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj PreScanOutputDev.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
cd ..
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 537ee1a..879a4f2 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "gmem.h"
#include "SplashErrorCodes.h"
#include "SplashMath.h"
@@ -28,6 +29,8 @@
//------------------------------------------------------------------------
+#define splashAAGamma 1.5
+
// distance of Bezier control point from center for circle approximation
// = (4 * (sqrt(2) - 1) / 3) * r
#define bezierCircle ((SplashCoord)0.55228475)
@@ -38,6 +41,52 @@ static inline Guchar div255(int x) {
return (Guchar)((x + (x >> 8) + 0x80) >> 8);
}
+// Clip x to lie in [0, 255].
+static inline Guchar clip255(int x) {
+ return x < 0 ? 0 : x > 255 ? 255 : x;
+}
+
+// The PDF spec says that all pixels whose *centers* lie within the
+// image target region get painted, so we want to round n+0.5 down to
+// n. But this causes problems, e.g., with PDF files that fill a
+// rectangle with black and then draw an image to the exact same
+// rectangle, so we instead use the fill scan conversion rule.
+// However, the correct rule works better for glyphs, so we also
+// provide that option in fillImageMask.
+#if 0
+static inline int imgCoordMungeLower(SplashCoord x) {
+ return splashCeil(x + 0.5) - 1;
+}
+static inline int imgCoordMungeUpper(SplashCoord x) {
+ return splashCeil(x + 0.5) - 1;
+}
+#else
+static inline int imgCoordMungeLower(SplashCoord x) {
+ return splashFloor(x);
+}
+static inline int imgCoordMungeUpper(SplashCoord x) {
+ return splashFloor(x) + 1;
+}
+static inline int imgCoordMungeLowerC(SplashCoord x, GBool glyphMode) {
+ return glyphMode ? (splashCeil(x + 0.5) - 1) : splashFloor(x);
+}
+static inline int imgCoordMungeUpperC(SplashCoord x, GBool glyphMode) {
+ return glyphMode ? (splashCeil(x + 0.5) - 1) : (splashFloor(x) + 1);
+}
+#endif
+
+// Used by drawImage and fillImageMask to divide the target
+// quadrilateral into sections.
+struct ImageSection {
+ int y0, y1; // actual y range
+ int ia0, ia1; // vertex indices for edge A
+ int ib0, ib1; // vertex indices for edge A
+ SplashCoord xa0, ya0, xa1, ya1; // edge A
+ SplashCoord dxdya; // slope of edge A
+ SplashCoord xb0, yb0, xb1, yb1; // edge B
+ SplashCoord dxdyb; // slope of edge B
+};
+
//------------------------------------------------------------------------
// SplashPipe
//------------------------------------------------------------------------
@@ -52,9 +101,8 @@ struct SplashPipe {
SplashPattern *pattern;
// source alpha and color
- SplashCoord aInput;
+ Guchar aInput;
GBool usesShape;
- Guchar aSrc;
SplashColorPtr cSrc;
SplashColor cSrcVal;
@@ -70,14 +118,17 @@ struct SplashPipe {
Guchar *destAlphaPtr;
// shape
- SplashCoord shape;
+ Guchar shape;
// result alpha and color
GBool noTransparency;
SplashPipeResultColorCtrl resultColorCtrl;
// non-isolated group correction
- int nonIsolatedGroup;
+ GBool nonIsolatedGroup;
+
+ // the "run" function
+ void (Splash::*run)(SplashPipe *pipe);
};
SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = {
@@ -159,7 +210,7 @@ inline void Splash::updateModY(int y) {
inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
SplashPattern *pattern, SplashColorPtr cSrc,
- SplashCoord aInput, GBool usesShape,
+ Guchar aInput, GBool usesShape,
GBool nonIsolatedGroup) {
pipeSetXY(pipe, x, y);
pipe->pattern = NULL;
@@ -178,18 +229,11 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
// source alpha
pipe->aInput = aInput;
- if (!state->softMask) {
- if (usesShape) {
- pipe->aInput *= 255;
- } else {
- pipe->aSrc = (Guchar)splashRound(pipe->aInput * 255);
- }
- }
pipe->usesShape = usesShape;
// result alpha
- if (aInput == 1 && !state->softMask && !usesShape &&
- !state->inNonIsolatedGroup) {
+ if (aInput == 255 && !state->softMask && !usesShape &&
+ !state->inNonIsolatedGroup && !nonIsolatedGroup) {
pipe->noTransparency = gTrue;
} else {
pipe->noTransparency = gFalse;
@@ -206,17 +250,54 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
}
// non-isolated group correction
- if (nonIsolatedGroup) {
- pipe->nonIsolatedGroup = splashColorModeNComps[bitmap->mode];
- } else {
- pipe->nonIsolatedGroup = 0;
+ pipe->nonIsolatedGroup = nonIsolatedGroup;
+
+ // select the 'run' function
+ pipe->run = &Splash::pipeRun;
+ if (!pipe->pattern && pipe->noTransparency && !state->blendFunc) {
+ if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunSimpleMono1;
+ } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunSimpleMono8;
+ } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunSimpleRGB8;
+ } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunSimpleBGR8;
+#if SPLASH_CMYK
+ } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunSimpleCMYK8;
+#endif
+ }
+ } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask &&
+ pipe->usesShape &&
+ !(state->inNonIsolatedGroup && alpha0Bitmap->alpha) &&
+ !state->blendFunc && !pipe->nonIsolatedGroup) {
+ if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunAAMono1;
+ } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunAAMono8;
+ } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunAARGB8;
+ } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunAABGR8;
+#if SPLASH_CMYK
+ } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
+ pipe->run = &Splash::pipeRunAACMYK8;
+#endif
+ }
}
}
-inline void Splash::pipeRun(SplashPipe *pipe) {
- Guchar aSrc, aDest, alpha2, alpha0, aResult;
- SplashColor cDest, cBlend;
+// general case
+void Splash::pipeRun(SplashPipe *pipe) {
+ Guchar aSrc, aDest, alphaI, alphaIm1, alpha0, aResult;
+ SplashColor cSrcNonIso, cDest, cBlend;
+ SplashColorPtr cSrc;
Guchar cResult0, cResult1, cResult2, cResult3;
+ int t;
+#if SPLASH_CMYK
+ SplashColor cSrc2, cDest2;
+#endif
//----- source color
@@ -234,7 +315,7 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
switch (bitmap->mode) {
case splashModeMono1:
- cResult0 = pipe->cSrc[0];
+ cResult0 = state->grayTransfer[pipe->cSrc[0]];
if (state->screen->test(pipe->x, pipe->y, cResult0)) {
*pipe->destColorPtr |= pipe->destColorMask;
} else {
@@ -246,24 +327,33 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
}
break;
case splashModeMono8:
- *pipe->destColorPtr++ = pipe->cSrc[0];
+ *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]];
break;
case splashModeRGB8:
- *pipe->destColorPtr++ = pipe->cSrc[0];
- *pipe->destColorPtr++ = pipe->cSrc[1];
- *pipe->destColorPtr++ = pipe->cSrc[2];
+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
break;
case splashModeBGR8:
- *pipe->destColorPtr++ = pipe->cSrc[2];
- *pipe->destColorPtr++ = pipe->cSrc[1];
- *pipe->destColorPtr++ = pipe->cSrc[0];
+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- *pipe->destColorPtr++ = pipe->cSrc[0];
- *pipe->destColorPtr++ = pipe->cSrc[1];
- *pipe->destColorPtr++ = pipe->cSrc[2];
- *pipe->destColorPtr++ = pipe->cSrc[3];
+ if (state->overprintMask & 1) {
+ pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
+ }
+ if (state->overprintMask & 2) {
+ pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
+ }
+ if (state->overprintMask & 4) {
+ pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
+ }
+ if (state->overprintMask & 8) {
+ pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
+ }
+ pipe->destColorPtr += 4;
break;
#endif
}
@@ -307,41 +397,98 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
aDest = 0xff;
}
- //----- blend function
-
- if (state->blendFunc) {
- (*state->blendFunc)(pipe->cSrc, cDest, cBlend, bitmap->mode);
- }
-
//----- source alpha
if (state->softMask) {
if (pipe->usesShape) {
- aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++
- * pipe->shape);
+ aSrc = div255(div255(pipe->aInput * *pipe->softMaskPtr++) *
+ pipe->shape);
} else {
- aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++);
+ aSrc = div255(pipe->aInput * *pipe->softMaskPtr++);
}
} else if (pipe->usesShape) {
- // pipe->aInput is premultiplied by 255 in pipeInit
- aSrc = (Guchar)splashRound(pipe->aInput * pipe->shape);
+ aSrc = div255(pipe->aInput * pipe->shape);
+ } else {
+ aSrc = pipe->aInput;
+ }
+
+ //----- non-isolated group correction
+
+ if (pipe->nonIsolatedGroup) {
+ // This path is only used when Splash::composite() is called to
+ // composite a non-isolated group onto the backdrop. In this
+ // case, pipe->shape is the source (group) alpha.
+ if (pipe->shape == 0) {
+ // this value will be multiplied by zero later, so it doesn't
+ // matter what we use
+ cSrc = pipe->cSrc;
+ } else {
+ t = (aDest * 255) / pipe->shape - aDest;
+ switch (bitmap->mode) {
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ cSrcNonIso[3] = clip255(pipe->cSrc[3] +
+ ((pipe->cSrc[3] - cDest[3]) * t) / 255);
+#endif
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cSrcNonIso[2] = clip255(pipe->cSrc[2] +
+ ((pipe->cSrc[2] - cDest[2]) * t) / 255);
+ cSrcNonIso[1] = clip255(pipe->cSrc[1] +
+ ((pipe->cSrc[1] - cDest[1]) * t) / 255);
+ case splashModeMono1:
+ case splashModeMono8:
+ cSrcNonIso[0] = clip255(pipe->cSrc[0] +
+ ((pipe->cSrc[0] - cDest[0]) * t) / 255);
+ break;
+ }
+ cSrc = cSrcNonIso;
+ }
} else {
- // precomputed in pipeInit
- aSrc = pipe->aSrc;
+ cSrc = pipe->cSrc;
+ }
+
+ //----- blend function
+
+ if (state->blendFunc) {
+#if SPLASH_CMYK
+ if (bitmap->mode == splashModeCMYK8) {
+ // convert colors to additive
+ cSrc2[0] = 0xff - cSrc[0];
+ cSrc2[1] = 0xff - cSrc[1];
+ cSrc2[2] = 0xff - cSrc[2];
+ cSrc2[3] = 0xff - cSrc[3];
+ cDest2[0] = 0xff - cDest[0];
+ cDest2[1] = 0xff - cDest[1];
+ cDest2[2] = 0xff - cDest[2];
+ cDest2[3] = 0xff - cDest[3];
+ (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode);
+ // convert result back to subtractive
+ cBlend[0] = 0xff - cBlend[0];
+ cBlend[1] = 0xff - cBlend[1];
+ cBlend[2] = 0xff - cBlend[2];
+ cBlend[3] = 0xff - cBlend[3];
+ } else
+#endif
+ (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode);
}
//----- result alpha and non-isolated group element correction
if (pipe->noTransparency) {
- alpha2 = aResult = 255;
+ alphaI = alphaIm1 = aResult = 255;
} else {
aResult = aSrc + aDest - div255(aSrc * aDest);
+ // alphaI = alpha_i
+ // alphaIm1 = alpha_(i-1)
if (pipe->alpha0Ptr) {
alpha0 = *pipe->alpha0Ptr++;
- alpha2 = aResult + alpha0 - div255(aResult * alpha0);
+ alphaI = aResult + alpha0 - div255(aResult * alpha0);
+ alphaIm1 = alpha0 + aDest - div255(alpha0 * aDest);
} else {
- alpha2 = aResult;
+ alphaI = aResult;
+ alphaIm1 = aDest;
}
}
@@ -351,140 +498,132 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
switch (pipe->resultColorCtrl) {
+ case splashPipeResultColorNoAlphaBlendMono:
+ cResult0 = state->grayTransfer[div255((255 - aDest) * cSrc[0] +
+ aDest * cBlend[0])];
+ break;
+ case splashPipeResultColorNoAlphaBlendRGB:
+ cResult0 = state->rgbTransferR[div255((255 - aDest) * cSrc[0] +
+ aDest * cBlend[0])];
+ cResult1 = state->rgbTransferG[div255((255 - aDest) * cSrc[1] +
+ aDest * cBlend[1])];
+ cResult2 = state->rgbTransferB[div255((255 - aDest) * cSrc[2] +
+ aDest * cBlend[2])];
+ break;
#if SPLASH_CMYK
case splashPipeResultColorNoAlphaBlendCMYK:
- cResult3 = div255((255 - aDest) * pipe->cSrc[3] + aDest * cBlend[3]);
-#endif
- case splashPipeResultColorNoAlphaBlendRGB:
- cResult2 = div255((255 - aDest) * pipe->cSrc[2] + aDest * cBlend[2]);
- cResult1 = div255((255 - aDest) * pipe->cSrc[1] + aDest * cBlend[1]);
- case splashPipeResultColorNoAlphaBlendMono:
- cResult0 = div255((255 - aDest) * pipe->cSrc[0] + aDest * cBlend[0]);
+ cResult0 = state->cmykTransferC[div255((255 - aDest) * cSrc[0] +
+ aDest * cBlend[0])];
+ cResult1 = state->cmykTransferM[div255((255 - aDest) * cSrc[1] +
+ aDest * cBlend[1])];
+ cResult2 = state->cmykTransferY[div255((255 - aDest) * cSrc[2] +
+ aDest * cBlend[2])];
+ cResult3 = state->cmykTransferK[div255((255 - aDest) * cSrc[3] +
+ aDest * cBlend[3])];
break;
+#endif
case splashPipeResultColorAlphaNoBlendMono:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * pipe->cSrc[0]) / alpha2);
+ cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / alphaI];
}
break;
case splashPipeResultColorAlphaNoBlendRGB:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * pipe->cSrc[0]) / alpha2);
- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
- aSrc * pipe->cSrc[1]) / alpha2);
- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
- aSrc * pipe->cSrc[2]) / alpha2);
+ cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / alphaI];
+ cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / alphaI];
+ cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / alphaI];
}
break;
#if SPLASH_CMYK
case splashPipeResultColorAlphaNoBlendCMYK:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * pipe->cSrc[0]) / alpha2);
- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
- aSrc * pipe->cSrc[1]) / alpha2);
- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
- aSrc * pipe->cSrc[2]) / alpha2);
- cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
- aSrc * pipe->cSrc[3]) / alpha2);
+ cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / alphaI];
+ cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / alphaI];
+ cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / alphaI];
+ cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / alphaI];
}
break;
#endif
case splashPipeResultColorAlphaBlendMono:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * ((255 - aDest) * pipe->cSrc[0] +
- aDest * cBlend[0]) / 255) /
- alpha2);
+ cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255) /
+ alphaI];
}
break;
case splashPipeResultColorAlphaBlendRGB:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * ((255 - aDest) * pipe->cSrc[0] +
- aDest * cBlend[0]) / 255) /
- alpha2);
- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
- aSrc * ((255 - aDest) * pipe->cSrc[1] +
- aDest * cBlend[1]) / 255) /
- alpha2);
- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
- aSrc * ((255 - aDest) * pipe->cSrc[2] +
- aDest * cBlend[2]) / 255) /
- alpha2);
+ cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255) /
+ alphaI];
+ cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255) /
+ alphaI];
+ cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255) /
+ alphaI];
}
break;
#if SPLASH_CMYK
case splashPipeResultColorAlphaBlendCMYK:
- if (alpha2 == 0) {
+ if (alphaI == 0) {
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
- aSrc * ((255 - aDest) * pipe->cSrc[0] +
- aDest * cBlend[0]) / 255) /
- alpha2);
- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
- aSrc * ((255 - aDest) * pipe->cSrc[1] +
- aDest * cBlend[1]) / 255) /
- alpha2);
- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
- aSrc * ((255 - aDest) * pipe->cSrc[2] +
- aDest * cBlend[2]) / 255) /
- alpha2);
- cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
- aSrc * ((255 - aDest) * pipe->cSrc[3] +
- aDest * cBlend[3]) / 255) /
- alpha2);
+ cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255) /
+ alphaI];
+ cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255) /
+ alphaI];
+ cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255) /
+ alphaI];
+ cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
+ aSrc * ((255 - alphaIm1) * cSrc[3] +
+ alphaIm1 * cBlend[3]) / 255) /
+ alphaI];
}
break;
#endif
}
- //----- non-isolated group correction
-
- if (aResult != 0) {
- switch (pipe->nonIsolatedGroup) {
-#if SPLASH_CMYK
- case 4:
- cResult3 += (cResult3 - cDest[3]) * aDest *
- (255 - aResult) / (255 * aResult);
-#endif
- case 3:
- cResult2 += (cResult2 - cDest[2]) * aDest *
- (255 - aResult) / (255 * aResult);
- cResult1 += (cResult1 - cDest[1]) * aDest *
- (255 - aResult) / (255 * aResult);
- case 1:
- cResult0 += (cResult0 - cDest[0]) * aDest *
- (255 - aResult) / (255 * aResult);
- case 0:
- break;
- }
- }
-
//----- write destination pixel
switch (bitmap->mode) {
@@ -514,10 +653,19 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- *pipe->destColorPtr++ = cResult0;
- *pipe->destColorPtr++ = cResult1;
- *pipe->destColorPtr++ = cResult2;
- *pipe->destColorPtr++ = cResult3;
+ if (state->overprintMask & 1) {
+ pipe->destColorPtr[0] = cResult0;
+ }
+ if (state->overprintMask & 2) {
+ pipe->destColorPtr[1] = cResult1;
+ }
+ if (state->overprintMask & 4) {
+ pipe->destColorPtr[2] = cResult2;
+ }
+ if (state->overprintMask & 8) {
+ pipe->destColorPtr[3] = cResult3;
+ }
+ pipe->destColorPtr += 4;
break;
#endif
}
@@ -530,6 +678,316 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
++pipe->x;
}
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
+void Splash::pipeRunSimpleMono1(SplashPipe *pipe) {
+ Guchar cResult0;
+
+ //----- write destination pixel
+ cResult0 = state->grayTransfer[pipe->cSrc[0]];
+ if (state->screen->test(pipe->x, pipe->y, cResult0)) {
+ *pipe->destColorPtr |= pipe->destColorMask;
+ } else {
+ *pipe->destColorPtr &= ~pipe->destColorMask;
+ }
+ if (!(pipe->destColorMask >>= 1)) {
+ pipe->destColorMask = 0x80;
+ ++pipe->destColorPtr;
+ }
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
+void Splash::pipeRunSimpleMono8(SplashPipe *pipe) {
+ //----- write destination pixel
+ *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]];
+ *pipe->destAlphaPtr++ = 255;
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
+void Splash::pipeRunSimpleRGB8(SplashPipe *pipe) {
+ //----- write destination pixel
+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
+ *pipe->destAlphaPtr++ = 255;
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
+void Splash::pipeRunSimpleBGR8(SplashPipe *pipe) {
+ //----- write destination pixel
+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
+ *pipe->destAlphaPtr++ = 255;
+
+ ++pipe->x;
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
+// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
+void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe) {
+ //----- write destination pixel
+ if (state->overprintMask & 1) {
+ pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
+ }
+ if (state->overprintMask & 2) {
+ pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
+ }
+ if (state->overprintMask & 4) {
+ pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
+ }
+ if (state->overprintMask & 8) {
+ pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
+ }
+ pipe->destColorPtr += 4;
+ *pipe->destAlphaPtr++ = 255;
+
+ ++pipe->x;
+}
+#endif
+
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr
+void Splash::pipeRunAAMono1(SplashPipe *pipe) {
+ Guchar aSrc;
+ SplashColor cDest;
+ Guchar cResult0;
+
+ //----- read destination pixel
+ cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00;
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * pipe->shape);
+
+ //----- result color
+ // note: aDest = alpha2 = aResult = 0xff
+ cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest[0] +
+ aSrc * pipe->cSrc[0])];
+
+ //----- write destination pixel
+ if (state->screen->test(pipe->x, pipe->y, cResult0)) {
+ *pipe->destColorPtr |= pipe->destColorMask;
+ } else {
+ *pipe->destColorPtr &= ~pipe->destColorMask;
+ }
+ if (!(pipe->destColorMask >>= 1)) {
+ pipe->destColorMask = 0x80;
+ ++pipe->destColorPtr;
+ }
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr
+void Splash::pipeRunAAMono8(SplashPipe *pipe) {
+ Guchar aSrc, aDest, alpha2, aResult;
+ SplashColor cDest;
+ Guchar cResult0;
+
+ //----- read destination pixel
+ cDest[0] = *pipe->destColorPtr;
+ aDest = *pipe->destAlphaPtr;
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * pipe->shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alpha2 = aResult;
+
+ //----- result color
+ if (alpha2 == 0) {
+ cResult0 = 0;
+ } else {
+ cResult0 = state->grayTransfer[(Guchar)(((alpha2 - aSrc) * cDest[0] +
+ aSrc * pipe->cSrc[0]) / alpha2)];
+ }
+
+ //----- write destination pixel
+ *pipe->destColorPtr++ = cResult0;
+ *pipe->destAlphaPtr++ = aResult;
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr
+void Splash::pipeRunAARGB8(SplashPipe *pipe) {
+ Guchar aSrc, aDest, alpha2, aResult;
+ SplashColor cDest;
+ Guchar cResult0, cResult1, cResult2;
+
+ //----- read destination pixel
+ cDest[0] = pipe->destColorPtr[0];
+ cDest[1] = pipe->destColorPtr[1];
+ cDest[2] = pipe->destColorPtr[2];
+ aDest = *pipe->destAlphaPtr;
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * pipe->shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alpha2 = aResult;
+
+ //----- result color
+ if (alpha2 == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] +
+ aSrc * pipe->cSrc[0]) / alpha2)];
+ cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] +
+ aSrc * pipe->cSrc[1]) / alpha2)];
+ cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] +
+ aSrc * pipe->cSrc[2]) / alpha2)];
+ }
+
+ //----- write destination pixel
+ *pipe->destColorPtr++ = cResult0;
+ *pipe->destColorPtr++ = cResult1;
+ *pipe->destColorPtr++ = cResult2;
+ *pipe->destAlphaPtr++ = aResult;
+
+ ++pipe->x;
+}
+
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr
+void Splash::pipeRunAABGR8(SplashPipe *pipe) {
+ Guchar aSrc, aDest, alpha2, aResult;
+ SplashColor cDest;
+ Guchar cResult0, cResult1, cResult2;
+
+ //----- read destination pixel
+ cDest[0] = pipe->destColorPtr[2];
+ cDest[1] = pipe->destColorPtr[1];
+ cDest[2] = pipe->destColorPtr[0];
+ aDest = *pipe->destAlphaPtr;
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * pipe->shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alpha2 = aResult;
+
+ //----- result color
+ if (alpha2 == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ } else {
+ cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] +
+ aSrc * pipe->cSrc[0]) / alpha2)];
+ cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] +
+ aSrc * pipe->cSrc[1]) / alpha2)];
+ cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] +
+ aSrc * pipe->cSrc[2]) / alpha2)];
+ }
+
+ //----- write destination pixel
+ *pipe->destColorPtr++ = cResult2;
+ *pipe->destColorPtr++ = cResult1;
+ *pipe->destColorPtr++ = cResult0;
+ *pipe->destAlphaPtr++ = aResult;
+
+ ++pipe->x;
+}
+
+#if SPLASH_CMYK
+// special case:
+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
+// !pipe->nonIsolatedGroup &&
+// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr
+void Splash::pipeRunAACMYK8(SplashPipe *pipe) {
+ Guchar aSrc, aDest, alpha2, aResult;
+ SplashColor cDest;
+ Guchar cResult0, cResult1, cResult2, cResult3;
+
+ //----- read destination pixel
+ cDest[0] = pipe->destColorPtr[0];
+ cDest[1] = pipe->destColorPtr[1];
+ cDest[2] = pipe->destColorPtr[2];
+ cDest[3] = pipe->destColorPtr[3];
+ aDest = *pipe->destAlphaPtr;
+
+ //----- source alpha
+ aSrc = div255(pipe->aInput * pipe->shape);
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alpha2 = aResult;
+
+ //----- result color
+ if (alpha2 == 0) {
+ cResult0 = 0;
+ cResult1 = 0;
+ cResult2 = 0;
+ cResult3 = 0;
+ } else {
+ cResult0 = state->cmykTransferC[(Guchar)(((alpha2 - aSrc) * cDest[0] +
+ aSrc * pipe->cSrc[0]) / alpha2)];
+ cResult1 = state->cmykTransferM[(Guchar)(((alpha2 - aSrc) * cDest[1] +
+ aSrc * pipe->cSrc[1]) / alpha2)];
+ cResult2 = state->cmykTransferY[(Guchar)(((alpha2 - aSrc) * cDest[2] +
+ aSrc * pipe->cSrc[2]) / alpha2)];
+ cResult3 = state->cmykTransferK[(Guchar)(((alpha2 - aSrc) * cDest[3] +
+ aSrc * pipe->cSrc[3]) / alpha2)];
+ }
+
+ //----- write destination pixel
+ if (state->overprintMask & 1) {
+ pipe->destColorPtr[0] = cResult0;
+ }
+ if (state->overprintMask & 2) {
+ pipe->destColorPtr[1] = cResult1;
+ }
+ if (state->overprintMask & 4) {
+ pipe->destColorPtr[2] = cResult2;
+ }
+ if (state->overprintMask & 8) {
+ pipe->destColorPtr[3] = cResult3;
+ }
+ pipe->destColorPtr += 4;
+ *pipe->destAlphaPtr++ = aResult;
+
+ ++pipe->x;
+}
+#endif
+
+
inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) {
pipe->x = x;
pipe->y = y;
@@ -605,7 +1063,7 @@ inline void Splash::pipeIncX(SplashPipe *pipe) {
inline void Splash::drawPixel(SplashPipe *pipe, int x, int y, GBool noClip) {
if (noClip || state->clip->test(x, y)) {
pipeSetXY(pipe, x, y);
- pipeRun(pipe);
+ (this->*pipe->run)(pipe);
updateModX(x);
updateModY(y);
}
@@ -666,8 +1124,8 @@ inline void Splash::drawAAPixel(SplashPipe *pipe, int x, int y) {
// draw the pixel
if (t != 0) {
pipeSetXY(pipe, x, y);
- pipe->shape *= aaGamma[t];
- pipeRun(pipe);
+ pipe->shape = div255(aaGamma[t] * pipe->shape);
+ (this->*pipe->run)(pipe);
updateModX(x);
updateModY(y);
}
@@ -677,18 +1135,25 @@ inline void Splash::drawSpan(SplashPipe *pipe, int x0, int x1, int y,
GBool noClip) {
int x;
- pipeSetXY(pipe, x0, y);
if (noClip) {
+ pipeSetXY(pipe, x0, y);
for (x = x0; x <= x1; ++x) {
- pipeRun(pipe);
+ (this->*pipe->run)(pipe);
}
updateModX(x0);
updateModX(x1);
updateModY(y);
} else {
+ if (x0 < state->clip->getXMinI()) {
+ x0 = state->clip->getXMinI();
+ }
+ if (x1 > state->clip->getXMaxI()) {
+ x1 = state->clip->getXMaxI();
+ }
+ pipeSetXY(pipe, x0, y);
for (x = x0; x <= x1; ++x) {
if (state->clip->test(x, y)) {
- pipeRun(pipe);
+ (this->*pipe->run)(pipe);
updateModX(x);
updateModY(y);
} else {
@@ -742,7 +1207,7 @@ inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y) {
if (t != 0) {
pipe->shape = aaGamma[t];
- pipeRun(pipe);
+ (this->*pipe->run)(pipe);
updateModX(x);
updateModY(y);
} else {
@@ -774,19 +1239,22 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
bitmap = bitmapA;
vectorAntialias = vectorAntialiasA;
+ inShading = gFalse;
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenParams);
if (vectorAntialias) {
aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize,
1, splashModeMono1, gFalse);
for (i = 0; i <= splashAASize * splashAASize; ++i) {
- aaGamma[i] = splashPow((SplashCoord)i /
- (SplashCoord)(splashAASize * splashAASize),
- 1.5);
+ aaGamma[i] = (Guchar)splashRound(
+ splashPow((SplashCoord)i /
+ (SplashCoord)(splashAASize * splashAASize),
+ splashAAGamma) * 255);
}
} else {
aaBuf = NULL;
}
+ minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
}
@@ -797,19 +1265,22 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
bitmap = bitmapA;
vectorAntialias = vectorAntialiasA;
+ inShading = gFalse;
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenA);
if (vectorAntialias) {
aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize,
1, splashModeMono1, gFalse);
for (i = 0; i <= splashAASize * splashAASize; ++i) {
- aaGamma[i] = splashPow((SplashCoord)i /
- (SplashCoord)(splashAASize * splashAASize),
- 1.5);
+ aaGamma[i] = (Guchar)splashRound(
+ splashPow((SplashCoord)i /
+ (SplashCoord)(splashAASize * splashAASize),
+ splashAAGamma) * 255);
}
} else {
aaBuf = NULL;
}
+ minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
}
@@ -888,6 +1359,10 @@ SplashCoord Splash::getLineDashPhase() {
return state->lineDashPhase;
}
+GBool Splash::getStrokeAdjust() {
+ return state->strokeAdjust;
+}
+
SplashClip *Splash::getClip() {
return state->clip;
}
@@ -991,6 +1466,15 @@ void Splash::setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA,
state->inNonIsolatedGroup = gTrue;
}
+void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
+ Guchar *gray) {
+ state->setTransfer(red, green, blue, gray);
+}
+
+void Splash::setOverprintMask(Guint overprintMask) {
+ state->overprintMask = overprintMask;
+}
+
//------------------------------------------------------------------------
// state save/restore
//------------------------------------------------------------------------
@@ -1122,6 +1606,7 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) {
SplashError Splash::stroke(SplashPath *path) {
SplashPath *path2, *dPath;
+ SplashCoord d1, d2, t1, t2, w;
if (debugMode) {
printf("stroke [dash:%d] [width:%.2f]:\n",
@@ -1137,12 +1622,44 @@ SplashError Splash::stroke(SplashPath *path) {
dPath = makeDashedPath(path2);
delete path2;
path2 = dPath;
+ if (path2->length == 0) {
+ delete path2;
+ return splashErrEmptyPath;
+ }
+ }
+
+ // transform a unit square, and take the half the max of the two
+ // diagonals; the product of this number and the line width is the
+ // (approximate) transformed line width
+ t1 = state->matrix[0] + state->matrix[2];
+ t2 = state->matrix[1] + state->matrix[3];
+ d1 = t1 * t1 + t2 * t2;
+ t1 = state->matrix[0] - state->matrix[2];
+ t2 = state->matrix[1] - state->matrix[3];
+ d2 = t1 * t1 + t2 * t2;
+ if (d2 > d1) {
+ d1 = d2;
}
- if (state->lineWidth == 0) {
- strokeNarrow(path2);
+ d1 *= 0.5;
+ if (d1 > 0 &&
+ d1 * state->lineWidth * state->lineWidth < minLineWidth * minLineWidth) {
+ w = minLineWidth / splashSqrt(d1);
+ strokeWide(path2, w);
+ } else if (bitmap->mode == splashModeMono1) {
+ // this gets close to Adobe's behavior in mono mode
+ if (d1 <= 2) {
+ strokeNarrow(path2);
+ } else {
+ strokeWide(path2, state->lineWidth);
+ }
} else {
- strokeWide(path2);
+ if (state->lineWidth == 0) {
+ strokeNarrow(path2);
+ } else {
+ strokeWide(path2, state->lineWidth);
+ }
}
+
delete path2;
return splashOk;
}
@@ -1151,8 +1668,8 @@ void Splash::strokeNarrow(SplashPath *path) {
SplashPipe pipe;
SplashXPath *xPath;
SplashXPathSeg *seg;
- int x0, x1, x2, x3, y0, y1, x, y, t;
- SplashCoord dx, dy, dxdy;
+ int x0, x1, y0, y1, xa, xb, y;
+ SplashCoord dxdy;
SplashClipResult clipRes;
int nClipRes[3];
int i;
@@ -1161,85 +1678,74 @@ void Splash::strokeNarrow(SplashPath *path) {
xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse);
- pipeInit(&pipe, 0, 0, state->strokePattern, NULL, state->strokeAlpha,
+ pipeInit(&pipe, 0, 0, state->strokePattern, NULL,
+ (Guchar)splashRound(state->strokeAlpha * 255),
gFalse, gFalse);
for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
-
- x0 = splashFloor(seg->x0);
- x1 = splashFloor(seg->x1);
- y0 = splashFloor(seg->y0);
- y1 = splashFloor(seg->y1);
-
- // horizontal segment
- if (y0 == y1) {
- if (x0 > x1) {
- t = x0; x0 = x1; x1 = t;
- }
- if ((clipRes = state->clip->testSpan(x0, x1, y0))
- != splashClipAllOutside) {
- drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside);
- }
-
- // segment with |dx| > |dy|
- } else if (splashAbs(seg->dxdy) > 1) {
- dx = seg->x1 - seg->x0;
- dy = seg->y1 - seg->y0;
- dxdy = seg->dxdy;
- if (y0 > y1) {
- t = y0; y0 = y1; y1 = t;
- t = x0; x0 = x1; x1 = t;
- dx = -dx;
- dy = -dy;
- }
- if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
- x0 <= x1 ? x1 : x0, y1))
- != splashClipAllOutside) {
- if (dx > 0) {
- x2 = x0;
- x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy);
- drawSpan(&pipe, x2, (x2 <= x3 - 1) ? x3 - 1 : x2, y0,
- clipRes == splashClipAllInside);
- x2 = x3;
- for (y = y0 + 1; y <= y1 - 1; ++y) {
- x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy);
- drawSpan(&pipe, x2, x3 - 1, y, clipRes == splashClipAllInside);
- x2 = x3;
+ if (seg->y0 <= seg->y1) {
+ y0 = splashFloor(seg->y0);
+ y1 = splashFloor(seg->y1);
+ x0 = splashFloor(seg->x0);
+ x1 = splashFloor(seg->x1);
+ } else {
+ y0 = splashFloor(seg->y1);
+ y1 = splashFloor(seg->y0);
+ x0 = splashFloor(seg->x1);
+ x1 = splashFloor(seg->x0);
+ }
+ if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
+ x0 <= x1 ? x1 : x0, y1))
+ != splashClipAllOutside) {
+ if (y0 == y1) {
+ if (x0 <= x1) {
+ drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside);
+ } else {
+ drawSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside);
+ }
+ } else {
+ dxdy = seg->dxdy;
+ if (y0 < state->clip->getYMinI()) {
+ y0 = state->clip->getYMinI();
+ x0 = splashFloor(seg->x0 + ((SplashCoord)y0 - seg->y0) * dxdy);
+ }
+ if (y1 > state->clip->getYMaxI()) {
+ y1 = state->clip->getYMaxI();
+ x1 = splashFloor(seg->x0 + ((SplashCoord)y1 - seg->y0) * dxdy);
+ }
+ if (x0 <= x1) {
+ xa = x0;
+ for (y = y0; y <= y1; ++y) {
+ if (y < y1) {
+ xb = splashFloor(seg->x0 +
+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
+ } else {
+ xb = x1 + 1;
+ }
+ if (xa == xb) {
+ drawPixel(&pipe, xa, y, clipRes == splashClipAllInside);
+ } else {
+ drawSpan(&pipe, xa, xb - 1, y, clipRes == splashClipAllInside);
+ }
+ xa = xb;
}
- drawSpan(&pipe, x2, x2 <= x1 ? x1 : x2, y1,
- clipRes == splashClipAllInside);
} else {
- x2 = x0;
- x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy);
- drawSpan(&pipe, (x3 + 1 <= x2) ? x3 + 1 : x2, x2, y0,
- clipRes == splashClipAllInside);
- x2 = x3;
- for (y = y0 + 1; y <= y1 - 1; ++y) {
- x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy);
- drawSpan(&pipe, x3 + 1, x2, y, clipRes == splashClipAllInside);
- x2 = x3;
+ xa = x0;
+ for (y = y0; y <= y1; ++y) {
+ if (y < y1) {
+ xb = splashFloor(seg->x0 +
+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
+ } else {
+ xb = x1 - 1;
+ }
+ if (xa == xb) {
+ drawPixel(&pipe, xa, y, clipRes == splashClipAllInside);
+ } else {
+ drawSpan(&pipe, xb + 1, xa, y, clipRes == splashClipAllInside);
+ }
+ xa = xb;
}
- drawSpan(&pipe, x1, (x1 <= x2) ? x2 : x1, y1,
- clipRes == splashClipAllInside);
- }
- }
-
- // segment with |dy| > |dx|
- } else {
- dxdy = seg->dxdy;
- if (y0 > y1) {
- t = x0; x0 = x1; x1 = t;
- t = y0; y0 = y1; y1 = t;
- }
- if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
- x0 <= x1 ? x1 : x0, y1))
- != splashClipAllOutside) {
- drawPixel(&pipe, x0, y0, clipRes == splashClipAllInside);
- for (y = y0 + 1; y <= y1 - 1; ++y) {
- x = splashFloor(seg->x0 + ((SplashCoord)y - seg->y0) * dxdy);
- drawPixel(&pipe, x, y, clipRes == splashClipAllInside);
}
- drawPixel(&pipe, x1, y1, clipRes == splashClipAllInside);
}
}
++nClipRes[clipRes];
@@ -1256,10 +1762,10 @@ void Splash::strokeNarrow(SplashPath *path) {
delete xPath;
}
-void Splash::strokeWide(SplashPath *path) {
+void Splash::strokeWide(SplashPath *path, SplashCoord w) {
SplashPath *path2;
- path2 = makeStrokePath(path, gFalse);
+ path2 = makeStrokePath(path, w, gFalse);
fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha);
delete path2;
}
@@ -1272,7 +1778,11 @@ SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix,
int i;
fPath = new SplashPath();
+#if USE_FIXEDPOINT
+ flatness2 = flatness;
+#else
flatness2 = flatness * flatness;
+#endif
i = 0;
while (i < path->length) {
flag = path->flags[i];
@@ -1337,13 +1847,21 @@ void Splash::flattenCurve(SplashCoord x0, SplashCoord y0,
// line)
transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my);
transform(matrix, xx1, yy1, &tx, &ty);
+#if USE_FIXEDPOINT
+ d1 = splashDist(tx, ty, mx, my);
+#else
dx = tx - mx;
dy = ty - my;
d1 = dx*dx + dy*dy;
+#endif
transform(matrix, xx2, yy2, &tx, &ty);
+#if USE_FIXEDPOINT
+ d2 = splashDist(tx, ty, mx, my);
+#else
dx = tx - mx;
dy = ty - my;
d2 = dx*dx + dy*dy;
+#endif
// if the curve is flat enough, or no more subdivisions are
// allowed, add the straight line segment
@@ -1353,18 +1871,18 @@ void Splash::flattenCurve(SplashCoord x0, SplashCoord y0,
// otherwise, subdivide the curve
} else {
- xl1 = (xl0 + xx1) * 0.5;
- yl1 = (yl0 + yy1) * 0.5;
- xh = (xx1 + xx2) * 0.5;
- yh = (yy1 + yy2) * 0.5;
- xl2 = (xl1 + xh) * 0.5;
- yl2 = (yl1 + yh) * 0.5;
- xr2 = (xx2 + xr3) * 0.5;
- yr2 = (yy2 + yr3) * 0.5;
- xr1 = (xh + xr2) * 0.5;
- yr1 = (yh + yr2) * 0.5;
- xr0 = (xl2 + xr1) * 0.5;
- yr0 = (yl2 + yr1) * 0.5;
+ xl1 = splashAvg(xl0, xx1);
+ yl1 = splashAvg(yl0, yy1);
+ xh = splashAvg(xx1, xx2);
+ yh = splashAvg(yy1, yy2);
+ xl2 = splashAvg(xl1, xh);
+ yl2 = splashAvg(yl1, yh);
+ xr2 = splashAvg(xx2, xr3);
+ yr2 = splashAvg(yy2, yr3);
+ xr1 = splashAvg(xh, xr2);
+ yr1 = splashAvg(yh, yr2);
+ xr0 = splashAvg(xl2, xr1);
+ yr0 = splashAvg(yl2, yr1);
// add the new subdivision points
p3 = (p1 + p2) / 2;
cx[p1][1] = xl1; cy[p1][1] = yl1;
@@ -1391,15 +1909,21 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
for (i = 0; i < state->lineDashLength; ++i) {
lineDashTotal += state->lineDash[i];
}
+ // Acrobat simply draws nothing if the dash array is [0]
+ if (lineDashTotal == 0) {
+ return new SplashPath();
+ }
lineDashStartPhase = state->lineDashPhase;
i = splashFloor(lineDashStartPhase / lineDashTotal);
lineDashStartPhase -= (SplashCoord)i * lineDashTotal;
lineDashStartOn = gTrue;
lineDashStartIdx = 0;
- while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
- lineDashStartOn = !lineDashStartOn;
- lineDashStartPhase -= state->lineDash[lineDashStartIdx];
- ++lineDashStartIdx;
+ if (lineDashStartPhase > 0) {
+ while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
+ lineDashStartOn = !lineDashStartOn;
+ lineDashStartPhase -= state->lineDash[lineDashStartIdx];
+ ++lineDashStartIdx;
+ }
}
dPath = new SplashPath();
@@ -1496,15 +2020,49 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
if (path->length == 0) {
return splashErrEmptyPath;
}
+ if (pathAllOutside(path)) {
+ opClipRes = splashClipAllOutside;
+ return splashOk;
+ }
+
+ // add stroke adjustment hints for filled rectangles -- this only
+ // applies to paths that consist of a single subpath
+ // (this appears to match Acrobat's behavior)
+ if (state->strokeAdjust && !path->hints) {
+ int n;
+ n = path->getLength();
+ if (n == 4 &&
+ !(path->flags[0] & splashPathClosed) &&
+ !(path->flags[1] & splashPathLast) &&
+ !(path->flags[2] & splashPathLast)) {
+ path->close(gTrue);
+ path->addStrokeAdjustHint(0, 2, 0, 4);
+ path->addStrokeAdjustHint(1, 3, 0, 4);
+ } else if (n == 5 &&
+ (path->flags[0] & splashPathClosed) &&
+ !(path->flags[1] & splashPathLast) &&
+ !(path->flags[2] & splashPathLast) &&
+ !(path->flags[3] & splashPathLast)) {
+ path->addStrokeAdjustHint(0, 2, 0, 4);
+ path->addStrokeAdjustHint(1, 3, 0, 4);
+ }
+ }
+
xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
- if (vectorAntialias) {
+ if (vectorAntialias && !inShading) {
xPath->aaScale();
}
xPath->sort();
- scanner = new SplashXPathScanner(xPath, eo);
+ yMinI = state->clip->getYMinI();
+ yMaxI = state->clip->getYMaxI();
+ if (vectorAntialias && !inShading) {
+ yMinI = yMinI * splashAASize;
+ yMaxI = (yMaxI + 1) * splashAASize - 1;
+ }
+ scanner = new SplashXPathScanner(xPath, eo, yMinI, yMaxI);
// get the min and max x and y values
- if (vectorAntialias) {
+ if (vectorAntialias && !inShading) {
scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
} else {
scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
@@ -1513,19 +2071,15 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
// check clipping
if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
!= splashClipAllOutside) {
-
- // limit the y range
- if (yMinI < state->clip->getYMinI()) {
- yMinI = state->clip->getYMinI();
- }
- if (yMaxI > state->clip->getYMaxI()) {
- yMaxI = state->clip->getYMaxI();
+ if (scanner->hasPartialClip()) {
+ clipRes = splashClipPartial;
}
- pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse);
+ pipeInit(&pipe, 0, yMinI, pattern, NULL, (Guchar)splashRound(alpha * 255),
+ vectorAntialias && !inShading, gFalse);
// draw the spans
- if (vectorAntialias) {
+ if (vectorAntialias && !inShading) {
for (y = yMinI; y <= yMaxI; ++y) {
scanner->renderAALine(aaBuf, &x0, &x1, y);
if (clipRes != splashClipAllInside) {
@@ -1560,6 +2114,73 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
return splashOk;
}
+GBool Splash::pathAllOutside(SplashPath *path) {
+ SplashCoord xMin1, yMin1, xMax1, yMax1;
+ SplashCoord xMin2, yMin2, xMax2, yMax2;
+ SplashCoord x, y;
+ int xMinI, yMinI, xMaxI, yMaxI;
+ int i;
+
+ xMin1 = xMax1 = path->pts[0].x;
+ yMin1 = yMax1 = path->pts[0].y;
+ for (i = 1; i < path->length; ++i) {
+ if (path->pts[i].x < xMin1) {
+ xMin1 = path->pts[i].x;
+ } else if (path->pts[i].x > xMax1) {
+ xMax1 = path->pts[i].x;
+ }
+ if (path->pts[i].y < yMin1) {
+ yMin1 = path->pts[i].y;
+ } else if (path->pts[i].y > yMax1) {
+ yMax1 = path->pts[i].y;
+ }
+ }
+
+ transform(state->matrix, xMin1, yMin1, &x, &y);
+ xMin2 = xMax2 = x;
+ yMin2 = yMax2 = y;
+ transform(state->matrix, xMin1, yMax1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ transform(state->matrix, xMax1, yMin1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ transform(state->matrix, xMax1, yMax1, &x, &y);
+ if (x < xMin2) {
+ xMin2 = x;
+ } else if (x > xMax2) {
+ xMax2 = x;
+ }
+ if (y < yMin2) {
+ yMin2 = y;
+ } else if (y > yMax2) {
+ yMax2 = y;
+ }
+ xMinI = splashFloor(xMin2);
+ yMinI = splashFloor(yMin2);
+ xMaxI = splashFloor(xMax2);
+ yMaxI = splashFloor(yMax2);
+
+ return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI) ==
+ splashClipAllOutside;
+}
+
SplashError Splash::xorFill(SplashPath *path, GBool eo) {
SplashPipe pipe;
SplashXPath *xPath;
@@ -1573,7 +2194,8 @@ SplashError Splash::xorFill(SplashPath *path, GBool eo) {
}
xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
xPath->sort();
- scanner = new SplashXPathScanner(xPath, eo);
+ scanner = new SplashXPathScanner(xPath, eo, state->clip->getYMinI(),
+ state->clip->getYMaxI());
// get the min and max x and y values
scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
@@ -1581,18 +2203,13 @@ SplashError Splash::xorFill(SplashPath *path, GBool eo) {
// check clipping
if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
!= splashClipAllOutside) {
-
- // limit the y range
- if (yMinI < state->clip->getYMinI()) {
- yMinI = state->clip->getYMinI();
- }
- if (yMaxI > state->clip->getYMaxI()) {
- yMaxI = state->clip->getYMaxI();
+ if (scanner->hasPartialClip()) {
+ clipRes = splashClipPartial;
}
origBlendFunc = state->blendFunc;
state->blendFunc = &blendXor;
- pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse);
+ pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 255, gFalse, gFalse);
// draw the spans
for (y = yMinI; y <= yMaxI; ++y) {
@@ -1662,7 +2279,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
SplashPipe pipe;
SplashClipResult clipRes;
GBool noClip;
- int alpha0, alpha;
+ int alpha0;
+ Guchar alpha;
Guchar *p;
int x1, y1, xx, xx1, yy;
@@ -1675,16 +2293,16 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
if (noClip) {
if (glyph->aa) {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
p = glyph->data;
for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
pipeSetXY(&pipe, x0 - glyph->x, y1);
for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
alpha = *p++;
if (alpha != 0) {
- pipe.shape = (SplashCoord)(alpha / 255.0);
- pipeRun(&pipe);
+ pipe.shape = alpha;
+ (this->*pipe.run)(&pipe);
updateModX(x1);
updateModY(y1);
} else {
@@ -1693,8 +2311,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
}
}
} else {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse);
p = glyph->data;
for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
pipeSetXY(&pipe, x0 - glyph->x, y1);
@@ -1702,7 +2320,7 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
alpha0 = *p++;
for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
if (alpha0 & 0x80) {
- pipeRun(&pipe);
+ (this->*pipe.run)(&pipe);
updateModX(x1);
updateModY(y1);
} else {
@@ -1715,8 +2333,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
}
} else {
if (glyph->aa) {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
p = glyph->data;
for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
pipeSetXY(&pipe, x0 - glyph->x, y1);
@@ -1724,8 +2342,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
if (state->clip->test(x1, y1)) {
alpha = *p++;
if (alpha != 0) {
- pipe.shape = (SplashCoord)(alpha / 255.0);
- pipeRun(&pipe);
+ pipe.shape = alpha;
+ (this->*pipe.run)(&pipe);
updateModX(x1);
updateModY(y1);
} else {
@@ -1738,8 +2356,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
}
}
} else {
- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse);
p = glyph->data;
for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
pipeSetXY(&pipe, x0 - glyph->x, y1);
@@ -1748,7 +2366,7 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
if (state->clip->test(x1, y1)) {
if (alpha0 & 0x80) {
- pipeRun(&pipe);
+ (this->*pipe.run)(&pipe);
updateModX(x1);
updateModY(y1);
} else {
@@ -1772,22 +2390,10 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
int w, int h, SplashCoord *mat,
GBool glyphMode) {
- SplashPipe pipe;
- GBool rot;
- SplashCoord xScale, yScale, xShear, yShear, yShear1;
- int tx, tx2, ty, ty2, scaledWidth, scaledHeight, xSign, ySign;
- int ulx, uly, llx, lly, urx, ury, lrx, lry;
- int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
- int xMin, xMax, yMin, yMax;
- SplashClipResult clipRes, clipRes2;
- int yp, yq, yt, yStep, lastYStep;
- int xp, xq, xt, xStep, xSrc;
- int k1, spanXMin, spanXMax, spanY;
- SplashColorPtr pixBuf, p;
- int pixAcc;
- int x, y, x1, x2, y2;
- SplashCoord y1;
- int n, m, i, j;
+ SplashBitmap *scaledMask;
+ SplashClipResult clipRes;
+ GBool minorAxisZero;
+ int x0, y0, x1, y1, scaledWidth, scaledHeight;
if (debugMode) {
printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
@@ -1796,286 +2402,729 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
}
// check for singular matrix
- if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) {
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) {
return splashErrSingularMatrix;
}
- // compute scale, shear, rotation, translation parameters
- rot = splashAbs(mat[1]) > splashAbs(mat[0]);
- if (rot) {
- xScale = -mat[1];
- yScale = mat[2] - (mat[0] * mat[3]) / mat[1];
- xShear = -mat[3] / yScale;
- yShear = -mat[0] / mat[1];
- } else {
- xScale = mat[0];
- yScale = mat[3] - (mat[1] * mat[2]) / mat[0];
- xShear = mat[2] / yScale;
- yShear = mat[1] / mat[0];
- }
- // Note 1: The PDF spec says that all pixels whose *centers* lie
- // within the region get painted -- but that doesn't seem to match
- // up with what Acrobat actually does: it ends up leaving gaps
- // between image stripes. So we use the same rule here as for
- // fills: any pixel that overlaps the region gets painted.
- // Note 2: The "glyphMode" flag is a kludge: it switches back to
- // "correct" behavior (matching the spec), for use in rendering Type
- // 3 fonts.
- // Note 3: The +/-0.01 in these computations is to avoid floating
- // point precision problems which can lead to gaps between image
- // stripes (it can cause image stripes to overlap, but that's a much
- // less visible problem).
- if (glyphMode) {
- if (xScale >= 0) {
- tx = splashRound(mat[4]);
- tx2 = splashRound(mat[4] + xScale) - 1;
- } else {
- tx = splashRound(mat[4]) - 1;
- tx2 = splashRound(mat[4] + xScale);
+ minorAxisZero = mat[1] == 0 && mat[2] == 0;
+
+ // scaling only
+ if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
+ x0 = imgCoordMungeLowerC(mat[4], glyphMode);
+ y0 = imgCoordMungeLowerC(mat[5], glyphMode);
+ x1 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode);
+ y1 = imgCoordMungeUpperC(mat[3] + mat[5], glyphMode);
+ // make sure narrow images cover at least one pixel
+ if (x0 == x1) {
+ ++x1;
+ }
+ if (y0 == y1) {
+ ++y1;
}
+ clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1);
+ opClipRes = clipRes;
+ if (clipRes != splashClipAllOutside) {
+ scaledWidth = x1 - x0;
+ scaledHeight = y1 - y0;
+ scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight);
+ blitMask(scaledMask, x0, y0, clipRes);
+ delete scaledMask;
+ }
+
+ // scaling plus vertical flip
+ } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) {
+ x0 = imgCoordMungeLowerC(mat[4], glyphMode);
+ y0 = imgCoordMungeLowerC(mat[3] + mat[5], glyphMode);
+ x1 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode);
+ y1 = imgCoordMungeUpperC(mat[5], glyphMode);
+ // make sure narrow images cover at least one pixel
+ if (x0 == x1) {
+ ++x1;
+ }
+ if (y0 == y1) {
+ ++y1;
+ }
+ clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1);
+ opClipRes = clipRes;
+ if (clipRes != splashClipAllOutside) {
+ scaledWidth = x1 - x0;
+ scaledHeight = y1 - y0;
+ scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight);
+ vertFlipImage(scaledMask, scaledWidth, scaledHeight, 1);
+ blitMask(scaledMask, x0, y0, clipRes);
+ delete scaledMask;
+ }
+
+ // all other cases
} else {
- if (xScale >= 0) {
- tx = splashFloor(mat[4] - 0.01);
- tx2 = splashFloor(mat[4] + xScale + 0.01);
- } else {
- tx = splashFloor(mat[4] + 0.01);
- tx2 = splashFloor(mat[4] + xScale - 0.01);
+ arbitraryTransformMask(src, srcData, w, h, mat, glyphMode);
+ }
+
+ return splashOk;
+}
+
+void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ SplashCoord *mat, GBool glyphMode) {
+ SplashBitmap *scaledMask;
+ SplashClipResult clipRes, clipRes2;
+ SplashPipe pipe;
+ int scaledWidth, scaledHeight, t0, t1;
+ SplashCoord r00, r01, r10, r11, det, ir00, ir01, ir10, ir11;
+ SplashCoord vx[4], vy[4];
+ int xMin, yMin, xMax, yMax;
+ ImageSection section[3];
+ int nSections;
+ int y, xa, xb, x, i, xx, yy;
+
+ // compute the four vertices of the target quadrilateral
+ vx[0] = mat[4]; vy[0] = mat[5];
+ vx[1] = mat[2] + mat[4]; vy[1] = mat[3] + mat[5];
+ vx[2] = mat[0] + mat[2] + mat[4]; vy[2] = mat[1] + mat[3] + mat[5];
+ vx[3] = mat[0] + mat[4]; vy[3] = mat[1] + mat[5];
+
+ // clipping
+ xMin = imgCoordMungeLowerC(vx[0], glyphMode);
+ xMax = imgCoordMungeUpperC(vx[0], glyphMode);
+ yMin = imgCoordMungeLowerC(vy[0], glyphMode);
+ yMax = imgCoordMungeUpperC(vy[0], glyphMode);
+ for (i = 1; i < 4; ++i) {
+ t0 = imgCoordMungeLowerC(vx[i], glyphMode);
+ if (t0 < xMin) {
+ xMin = t0;
+ }
+ t0 = imgCoordMungeUpperC(vx[i], glyphMode);
+ if (t0 > xMax) {
+ xMax = t0;
}
+ t1 = imgCoordMungeLowerC(vy[i], glyphMode);
+ if (t1 < yMin) {
+ yMin = t1;
+ }
+ t1 = imgCoordMungeUpperC(vy[i], glyphMode);
+ if (t1 > yMax) {
+ yMax = t1;
+ }
+ }
+ clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1);
+ opClipRes = clipRes;
+ if (clipRes == splashClipAllOutside) {
+ return;
+ }
+
+ // compute the scale factors
+ if (mat[0] >= 0) {
+ t0 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode) -
+ imgCoordMungeLowerC(mat[4], glyphMode);
+ } else {
+ t0 = imgCoordMungeUpperC(mat[4], glyphMode) -
+ imgCoordMungeLowerC(mat[0] + mat[4], glyphMode);
+ }
+ if (mat[1] >= 0) {
+ t1 = imgCoordMungeUpperC(mat[1] + mat[5], glyphMode) -
+ imgCoordMungeLowerC(mat[5], glyphMode);
+ } else {
+ t1 = imgCoordMungeUpperC(mat[5], glyphMode) -
+ imgCoordMungeLowerC(mat[1] + mat[5], glyphMode);
+ }
+ scaledWidth = t0 > t1 ? t0 : t1;
+ if (mat[2] >= 0) {
+ t0 = imgCoordMungeUpperC(mat[2] + mat[4], glyphMode) -
+ imgCoordMungeLowerC(mat[4], glyphMode);
+ } else {
+ t0 = imgCoordMungeUpperC(mat[4], glyphMode) -
+ imgCoordMungeLowerC(mat[2] + mat[4], glyphMode);
}
- scaledWidth = abs(tx2 - tx) + 1;
- if (glyphMode) {
- if (yScale >= 0) {
- ty = splashRound(mat[5]);
- ty2 = splashRound(mat[5] + yScale) - 1;
+ if (mat[3] >= 0) {
+ t1 = imgCoordMungeUpperC(mat[3] + mat[5], glyphMode) -
+ imgCoordMungeLowerC(mat[5], glyphMode);
+ } else {
+ t1 = imgCoordMungeUpperC(mat[5], glyphMode) -
+ imgCoordMungeLowerC(mat[3] + mat[5], glyphMode);
+ }
+ scaledHeight = t0 > t1 ? t0 : t1;
+ if (scaledWidth == 0) {
+ scaledWidth = 1;
+ }
+ if (scaledHeight == 0) {
+ scaledHeight = 1;
+ }
+
+ // compute the inverse transform (after scaling) matrix
+ r00 = mat[0] / scaledWidth;
+ r01 = mat[1] / scaledWidth;
+ r10 = mat[2] / scaledHeight;
+ r11 = mat[3] / scaledHeight;
+ det = r00 * r11 - r01 * r10;
+ if (splashAbs(det) < 1e-6) {
+ // this should be caught by the singular matrix check in fillImageMask
+ return;
+ }
+ ir00 = r11 / det;
+ ir01 = -r01 / det;
+ ir10 = -r10 / det;
+ ir11 = r00 / det;
+
+ // scale the input image
+ scaledMask = scaleMask(src, srcData, srcWidth, srcHeight,
+ scaledWidth, scaledHeight);
+
+ // construct the three sections
+ i = (vy[2] <= vy[3]) ? 2 : 3;
+ if (vy[1] <= vy[i]) {
+ i = 1;
+ }
+ if (vy[0] < vy[i] || (i != 3 && vy[0] == vy[i])) {
+ i = 0;
+ }
+ if (vy[i] == vy[(i+1) & 3]) {
+ section[0].y0 = imgCoordMungeLowerC(vy[i], glyphMode);
+ section[0].y1 = imgCoordMungeUpperC(vy[(i+2) & 3], glyphMode) - 1;
+ if (vx[i] < vx[(i+1) & 3]) {
+ section[0].ia0 = i;
+ section[0].ia1 = (i+3) & 3;
+ section[0].ib0 = (i+1) & 3;
+ section[0].ib1 = (i+2) & 3;
} else {
- ty = splashRound(mat[5]) - 1;
- ty2 = splashRound(mat[5] + yScale);
+ section[0].ia0 = (i+1) & 3;
+ section[0].ia1 = (i+2) & 3;
+ section[0].ib0 = i;
+ section[0].ib1 = (i+3) & 3;
}
+ nSections = 1;
} else {
- if (yScale >= 0) {
- ty = splashFloor(mat[5] - 0.01);
- ty2 = splashFloor(mat[5] + yScale + 0.01);
+ section[0].y0 = imgCoordMungeLowerC(vy[i], glyphMode);
+ section[2].y1 = imgCoordMungeUpperC(vy[(i+2) & 3], glyphMode) - 1;
+ section[0].ia0 = section[0].ib0 = i;
+ section[2].ia1 = section[2].ib1 = (i+2) & 3;
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[0].ia1 = section[2].ia0 = (i+1) & 3;
+ section[0].ib1 = section[2].ib0 = (i+3) & 3;
} else {
- ty = splashFloor(mat[5] + 0.01);
- ty2 = splashFloor(mat[5] + yScale - 0.01);
+ section[0].ia1 = section[2].ia0 = (i+3) & 3;
+ section[0].ib1 = section[2].ib0 = (i+1) & 3;
+ }
+ if (vy[(i+1) & 3] < vy[(i+3) & 3]) {
+ section[1].y0 = imgCoordMungeLowerC(vy[(i+1) & 3], glyphMode);
+ section[2].y0 = imgCoordMungeUpperC(vy[(i+3) & 3], glyphMode);
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[1].ia0 = (i+1) & 3;
+ section[1].ia1 = (i+2) & 3;
+ section[1].ib0 = i;
+ section[1].ib1 = (i+3) & 3;
+ } else {
+ section[1].ia0 = i;
+ section[1].ia1 = (i+3) & 3;
+ section[1].ib0 = (i+1) & 3;
+ section[1].ib1 = (i+2) & 3;
+ }
+ } else {
+ section[1].y0 = imgCoordMungeLowerC(vy[(i+3) & 3], glyphMode);
+ section[2].y0 = imgCoordMungeUpperC(vy[(i+1) & 3], glyphMode);
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[1].ia0 = i;
+ section[1].ia1 = (i+1) & 3;
+ section[1].ib0 = (i+3) & 3;
+ section[1].ib1 = (i+2) & 3;
+ } else {
+ section[1].ia0 = (i+3) & 3;
+ section[1].ia1 = (i+2) & 3;
+ section[1].ib0 = i;
+ section[1].ib1 = (i+1) & 3;
+ }
}
+ section[0].y1 = section[1].y0 - 1;
+ section[1].y1 = section[2].y0 - 1;
+ nSections = 3;
+ }
+ for (i = 0; i < nSections; ++i) {
+ section[i].xa0 = vx[section[i].ia0];
+ section[i].ya0 = vy[section[i].ia0];
+ section[i].xa1 = vx[section[i].ia1];
+ section[i].ya1 = vy[section[i].ia1];
+ section[i].xb0 = vx[section[i].ib0];
+ section[i].yb0 = vy[section[i].ib0];
+ section[i].xb1 = vx[section[i].ib1];
+ section[i].yb1 = vy[section[i].ib1];
+ section[i].dxdya = (section[i].xa1 - section[i].xa0) /
+ (section[i].ya1 - section[i].ya0);
+ section[i].dxdyb = (section[i].xb1 - section[i].xb0) /
+ (section[i].yb1 - section[i].yb0);
}
- scaledHeight = abs(ty2 - ty) + 1;
- xSign = (xScale < 0) ? -1 : 1;
- ySign = (yScale < 0) ? -1 : 1;
- yShear1 = (SplashCoord)xSign * yShear;
- // clipping
- ulx1 = 0;
- uly1 = 0;
- urx1 = xSign * (scaledWidth - 1);
- ury1 = (int)(yShear * urx1);
- llx1 = splashRound(xShear * ySign * (scaledHeight - 1));
- lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1);
- lrx1 = xSign * (scaledWidth - 1) +
- splashRound(xShear * ySign * (scaledHeight - 1));
- lry1 = ySign * (scaledHeight - 1) + (int)(yShear * lrx1);
- if (rot) {
- ulx = tx + uly1; uly = ty - ulx1;
- urx = tx + ury1; ury = ty - urx1;
- llx = tx + lly1; lly = ty - llx1;
- lrx = tx + lry1; lry = ty - lrx1;
+ // initialize the pixel pipe
+ pipeInit(&pipe, 0, 0, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
+ if (vectorAntialias) {
+ drawAAPixelInit();
+ }
+
+ // make sure narrow images cover at least one pixel
+ if (nSections == 1) {
+ if (section[0].y0 == section[0].y1) {
+ ++section[0].y1;
+ clipRes = opClipRes = splashClipPartial;
+ }
} else {
- ulx = tx + ulx1; uly = ty + uly1;
- urx = tx + urx1; ury = ty + ury1;
- llx = tx + llx1; lly = ty + lly1;
- lrx = tx + lrx1; lry = ty + lry1;
- }
- xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
- : (llx < lrx) ? llx : lrx
- : (urx < llx) ? (urx < lrx) ? urx : lrx
- : (llx < lrx) ? llx : lrx;
- xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
- : (llx > lrx) ? llx : lrx
- : (urx > llx) ? (urx > lrx) ? urx : lrx
- : (llx > lrx) ? llx : lrx;
- yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
- : (lly < lry) ? lly : lry
- : (ury < lly) ? (ury < lry) ? ury : lry
- : (lly < lry) ? lly : lry;
- yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
- : (lly > lry) ? lly : lry
- : (ury > lly) ? (ury > lry) ? ury : lry
- : (lly > lry) ? lly : lry;
- clipRes = state->clip->testRect(xMin, yMin, xMax, yMax);
- opClipRes = clipRes;
+ if (section[0].y0 == section[2].y1) {
+ ++section[1].y1;
+ clipRes = opClipRes = splashClipPartial;
+ }
+ }
- // compute Bresenham parameters for x and y scaling
- yp = h / scaledHeight;
- yq = h % scaledHeight;
- xp = w / scaledWidth;
- xq = w % scaledWidth;
+ // scan all pixels inside the target region
+ for (i = 0; i < nSections; ++i) {
+ for (y = section[i].y0; y <= section[i].y1; ++y) {
+ xa = imgCoordMungeLowerC(section[i].xa0 +
+ ((SplashCoord)y + 0.5 - section[i].ya0) *
+ section[i].dxdya,
+ glyphMode);
+ xb = imgCoordMungeUpperC(section[i].xb0 +
+ ((SplashCoord)y + 0.5 - section[i].yb0) *
+ section[i].dxdyb,
+ glyphMode);
+ // make sure narrow images cover at least one pixel
+ if (xa == xb) {
+ ++xb;
+ }
+ if (clipRes != splashClipAllInside) {
+ clipRes2 = state->clip->testSpan(xa, xb - 1, y);
+ } else {
+ clipRes2 = clipRes;
+ }
+ for (x = xa; x < xb; ++x) {
+ // map (x+0.5, y+0.5) back to the scaled image
+ xx = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir00 +
+ ((SplashCoord)y + 0.5 - mat[5]) * ir10);
+ yy = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir01 +
+ ((SplashCoord)y + 0.5 - mat[5]) * ir11);
+ // xx should always be within bounds, but floating point
+ // inaccuracy can cause problems
+ if (xx < 0) {
+ xx = 0;
+ } else if (xx >= scaledWidth) {
+ xx = scaledWidth - 1;
+ }
+ if (yy < 0) {
+ yy = 0;
+ } else if (yy >= scaledHeight) {
+ yy = scaledHeight - 1;
+ }
+ pipe.shape = scaledMask->data[yy * scaledWidth + xx];
+ if (vectorAntialias && clipRes2 != splashClipAllInside) {
+ drawAAPixel(&pipe, x, y);
+ } else {
+ drawPixel(&pipe, x, y, clipRes2 == splashClipAllInside);
+ }
+ }
+ }
+ }
- // allocate pixel buffer
- pixBuf = (SplashColorPtr)gmalloc((yp + 1) * w);
+ delete scaledMask;
+}
- // initialize the pixel pipe
- pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha,
- gTrue, gFalse);
- if (vectorAntialias) {
- drawAAPixelInit();
+// Scale an image mask into a SplashBitmap.
+SplashBitmap *Splash::scaleMask(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight) {
+ SplashBitmap *dest;
+
+ dest = new SplashBitmap(scaledWidth, scaledHeight, 1, splashModeMono8,
+ gFalse);
+ if (scaledHeight < srcHeight) {
+ if (scaledWidth < srcWidth) {
+ scaleMaskYdXd(src, srcData, srcWidth, srcHeight,
+ scaledWidth, scaledHeight, dest);
+ } else {
+ scaleMaskYdXu(src, srcData, srcWidth, srcHeight,
+ scaledWidth, scaledHeight, dest);
+ }
+ } else {
+ if (scaledWidth < srcWidth) {
+ scaleMaskYuXd(src, srcData, srcWidth, srcHeight,
+ scaledWidth, scaledHeight, dest);
+ } else {
+ scaleMaskYuXu(src, srcData, srcWidth, srcHeight,
+ scaledWidth, scaledHeight, dest);
+ }
}
+ return dest;
+}
+
+void Splash::scaleMaskYdXd(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf;
+ Guint *pixBuf;
+ Guint pix;
+ Guchar *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx, d, d0, d1;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+
+ // Bresenham parameters for x scale
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmalloc(srcWidth);
+ pixBuf = (Guint *)gmallocn(srcWidth, sizeof(int));
// init y scale Bresenham
yt = 0;
- lastYStep = 1;
+ destPtr = dest->data;
for (y = 0; y < scaledHeight; ++y) {
// y scale Bresenham
- yStep = yp;
- yt += yq;
- if (yt >= scaledHeight) {
+ if ((yt += yq) >= scaledHeight) {
yt -= scaledHeight;
- ++yStep;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
}
- // read row(s) from image
- n = (yp > 0) ? yStep : lastYStep;
- if (n > 0) {
- p = pixBuf;
- for (i = 0; i < n; ++i) {
- (*src)(srcData, p);
- p += w;
+ // read rows from image
+ memset(pixBuf, 0, srcWidth * sizeof(int));
+ for (i = 0; i < yStep; ++i) {
+ (*src)(srcData, lineBuf);
+ for (j = 0; j < srcWidth; ++j) {
+ pixBuf[j] += lineBuf[j];
}
}
- lastYStep = yStep;
- // loop-invariant constants
- k1 = splashRound(xShear * ySign * y);
+ // init x scale Bresenham
+ xt = 0;
+ d0 = (255 << 23) / (yStep * xp);
+ d1 = (255 << 23) / (yStep * (xp + 1));
+
+ xx = 0;
+ for (x = 0; x < scaledWidth; ++x) {
- // clipping test
- if (clipRes != splashClipAllInside &&
- !rot &&
- (int)(yShear * k1) ==
- (int)(yShear * (xSign * (scaledWidth - 1) + k1))) {
- if (xSign > 0) {
- spanXMin = tx + k1;
- spanXMax = spanXMin + (scaledWidth - 1);
+ // x scale Bresenham
+ if ((xt += xq) >= scaledWidth) {
+ xt -= scaledWidth;
+ xStep = xp + 1;
+ d = d1;
} else {
- spanXMax = tx + k1;
- spanXMin = spanXMax - (scaledWidth - 1);
+ xStep = xp;
+ d = d0;
}
- spanY = ty + ySign * y + (int)(yShear * k1);
- clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY);
- if (clipRes2 == splashClipAllOutside) {
- continue;
+
+ // compute the final pixel
+ pix = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix += pixBuf[xx++];
}
+ // (255 * pix) / xStep * yStep
+ pix = (pix * d) >> 23;
+
+ // store the pixel
+ *destPtr++ = (Guchar)pix;
+ }
+ }
+
+ gfree(pixBuf);
+ gfree(lineBuf);
+}
+
+void Splash::scaleMaskYdXu(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf;
+ Guint *pixBuf;
+ Guint pix;
+ Guchar *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, d;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+
+ // Bresenham parameters for x scale
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmalloc(srcWidth);
+ pixBuf = (Guint *)gmallocn(srcWidth, sizeof(int));
+
+ // init y scale Bresenham
+ yt = 0;
+
+ destPtr = dest->data;
+ for (y = 0; y < scaledHeight; ++y) {
+
+ // y scale Bresenham
+ if ((yt += yq) >= scaledHeight) {
+ yt -= scaledHeight;
+ yStep = yp + 1;
} else {
- clipRes2 = clipRes;
+ yStep = yp;
+ }
+
+ // read rows from image
+ memset(pixBuf, 0, srcWidth * sizeof(int));
+ for (i = 0; i < yStep; ++i) {
+ (*src)(srcData, lineBuf);
+ for (j = 0; j < srcWidth; ++j) {
+ pixBuf[j] += lineBuf[j];
+ }
}
// init x scale Bresenham
xt = 0;
- xSrc = 0;
+ d = (255 << 23) / yStep;
- // x shear
- x1 = k1;
+ for (x = 0; x < srcWidth; ++x) {
- // y shear
- y1 = (SplashCoord)ySign * y + yShear * x1;
- // this is a kludge: if yShear1 is negative, then (int)y1 would
- // change immediately after the first pixel, which is not what we
- // want
- if (yShear1 < 0) {
- y1 += 0.999;
+ // x scale Bresenham
+ if ((xt += xq) >= srcWidth) {
+ xt -= srcWidth;
+ xStep = xp + 1;
+ } else {
+ xStep = xp;
+ }
+
+ // compute the final pixel
+ pix = pixBuf[x];
+ // (255 * pix) / yStep
+ pix = (pix * d) >> 23;
+
+ // store the pixel
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = (Guchar)pix;
+ }
}
+ }
+
+ gfree(pixBuf);
+ gfree(lineBuf);
+}
+
+void Splash::scaleMaskYuXd(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf;
+ Guint pix;
+ Guchar *destPtr0, *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx, d, d0, d1;
+ int i;
+
+ // Bresenham parameters for y scale
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
- // loop-invariant constants
- n = yStep > 0 ? yStep : 1;
+ // Bresenham parameters for x scale
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+ // allocate buffers
+ lineBuf = (Guchar *)gmalloc(srcWidth);
+
+ // init y scale Bresenham
+ yt = 0;
+
+ destPtr0 = dest->data;
+ for (y = 0; y < srcHeight; ++y) {
+
+ // y scale Bresenham
+ if ((yt += yq) >= srcHeight) {
+ yt -= srcHeight;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
+ }
+
+ // read row from image
+ (*src)(srcData, lineBuf);
+
+ // init x scale Bresenham
+ xt = 0;
+ d0 = (255 << 23) / xp;
+ d1 = (255 << 23) / (xp + 1);
+
+ xx = 0;
for (x = 0; x < scaledWidth; ++x) {
// x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
+ if ((xt += xq) >= scaledWidth) {
xt -= scaledWidth;
- ++xStep;
- }
-
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
+ xStep = xp + 1;
+ d = d1;
} else {
- x2 = x1;
- y2 = (int)y1;
+ xStep = xp;
+ d = d0;
}
- // compute the alpha value for (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- p = pixBuf + xSrc;
- pixAcc = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc += *p++;
- }
- p += w - m;
+ // compute the final pixel
+ pix = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix += lineBuf[xx++];
}
+ // (255 * pix) / xStep
+ pix = (pix * d) >> 23;
- // blend fill color with background
- if (pixAcc != 0) {
- pipe.shape = (pixAcc == n * m)
- ? (SplashCoord)1
- : (SplashCoord)pixAcc / (SplashCoord)(n * m);
- if (vectorAntialias && clipRes2 != splashClipAllInside) {
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2, clipRes2 == splashClipAllInside);
- }
+ // store the pixel
+ for (i = 0; i < yStep; ++i) {
+ destPtr = destPtr0 + i * scaledWidth + x;
+ *destPtr = (Guchar)pix;
}
+ }
+
+ destPtr0 += yStep * scaledWidth;
+ }
+
+ gfree(lineBuf);
+}
+
+void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf;
+ Guint pix;
+ Guchar *destPtr0, *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
+
+ // Bresenham parameters for x scale
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmalloc(srcWidth);
+
+ // init y scale Bresenham
+ yt = 0;
+
+ destPtr0 = dest->data;
+ for (y = 0; y < srcHeight; ++y) {
+
+ // y scale Bresenham
+ if ((yt += yq) >= srcHeight) {
+ yt -= srcHeight;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
+ }
+
+ // read row from image
+ (*src)(srcData, lineBuf);
+
+ // init x scale Bresenham
+ xt = 0;
+
+ xx = 0;
+ for (x = 0; x < srcWidth; ++x) {
// x scale Bresenham
- xSrc += xStep;
+ if ((xt += xq) >= srcWidth) {
+ xt -= srcWidth;
+ xStep = xp + 1;
+ } else {
+ xStep = xp;
+ }
- // x shear
- x1 += xSign;
+ // compute the final pixel
+ pix = lineBuf[x] ? 255 : 0;
+
+ // store the pixel
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destPtr = destPtr0 + i * scaledWidth + xx + j;
+ *destPtr++ = (Guchar)pix;
+ }
+ }
- // y shear
- y1 += yShear1;
+ xx += xStep;
}
+
+ destPtr0 += yStep * scaledWidth;
}
- // free memory
- gfree(pixBuf);
+ gfree(lineBuf);
+}
- return splashOk;
+void Splash::blitMask(SplashBitmap *src, int xDest, int yDest,
+ SplashClipResult clipRes) {
+ SplashPipe pipe;
+ Guchar *p;
+ int w, h, x, y;
+
+ w = src->getWidth();
+ h = src->getHeight();
+ if (vectorAntialias && clipRes != splashClipAllInside) {
+ pipeInit(&pipe, xDest, yDest, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
+ drawAAPixelInit();
+ p = src->getDataPtr();
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ pipe.shape = *p++;
+ drawAAPixel(&pipe, xDest + x, yDest + y);
+ }
+ }
+ } else {
+ pipeInit(&pipe, xDest, yDest, state->fillPattern, NULL,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
+ p = src->getDataPtr();
+ if (clipRes == splashClipAllInside) {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ if (*p) {
+ pipe.shape = *p;
+ (this->*pipe.run)(&pipe);
+ } else {
+ pipeIncX(&pipe);
+ }
+ ++p;
+ }
+ }
+ updateModX(xDest);
+ updateModX(xDest + w - 1);
+ updateModY(yDest);
+ updateModY(yDest + h - 1);
+ } else {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ if (*p && state->clip->test(xDest + x, yDest + y)) {
+ pipe.shape = *p;
+ (this->*pipe.run)(&pipe);
+ updateModX(xDest + x);
+ updateModY(yDest + y);
+ } else {
+ pipeIncX(&pipe);
+ }
+ ++p;
+ }
+ }
+ }
+ }
}
SplashError Splash::drawImage(SplashImageSource src, void *srcData,
SplashColorMode srcMode, GBool srcAlpha,
int w, int h, SplashCoord *mat) {
- SplashPipe pipe;
- GBool ok, rot;
- SplashCoord xScale, yScale, xShear, yShear, yShear1;
- int tx, tx2, ty, ty2, scaledWidth, scaledHeight, xSign, ySign;
- int ulx, uly, llx, lly, urx, ury, lrx, lry;
- int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
- int xMin, xMax, yMin, yMax;
- SplashClipResult clipRes, clipRes2;
- int yp, yq, yt, yStep, lastYStep;
- int xp, xq, xt, xStep, xSrc;
- int k1, spanXMin, spanXMax, spanY;
- SplashColorPtr colorBuf, p;
- SplashColor pix;
- Guchar *alphaBuf, *q;
-#if SPLASH_CMYK
- int pixAcc0, pixAcc1, pixAcc2, pixAcc3;
-#else
- int pixAcc0, pixAcc1, pixAcc2;
-#endif
- int alphaAcc;
- SplashCoord pixMul, alphaMul, alpha;
- int x, y, x1, x2, y2;
- SplashCoord y1;
- int nComps, n, m, i, j;
+ GBool ok;
+ SplashBitmap *scaledImg;
+ SplashClipResult clipRes;
+ GBool minorAxisZero;
+ int x0, y0, x1, y1, scaledWidth, scaledHeight;
+ int nComps;
if (debugMode) {
printf("drawImage: srcMode=%d srcAlpha=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
@@ -2106,666 +3155,1170 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
nComps = 4;
break;
#endif
+ default:
+ ok = gFalse;
+ break;
}
if (!ok) {
return splashErrModeMismatch;
}
// check for singular matrix
- if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) {
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) {
return splashErrSingularMatrix;
}
- // compute scale, shear, rotation, translation parameters
- rot = splashAbs(mat[1]) > splashAbs(mat[0]);
- if (rot) {
- xScale = -mat[1];
- yScale = mat[2] - (mat[0] * mat[3]) / mat[1];
- xShear = -mat[3] / yScale;
- yShear = -mat[0] / mat[1];
- } else {
- xScale = mat[0];
- yScale = mat[3] - (mat[1] * mat[2]) / mat[0];
- xShear = mat[2] / yScale;
- yShear = mat[1] / mat[0];
- }
- // Note 1: The PDF spec says that all pixels whose *centers* lie
- // within the region get painted -- but that doesn't seem to match
- // up with what Acrobat actually does: it ends up leaving gaps
- // between image stripes. So we use the same rule here as for
- // fills: any pixel that overlaps the region gets painted.
- // Note 2: The +/-0.01 in these computations is to avoid floating
- // point precision problems which can lead to gaps between image
- // stripes (it can cause image stripes to overlap, but that's a much
- // less visible problem).
- if (xScale >= 0) {
- tx = splashFloor(mat[4] - 0.01);
- tx2 = splashFloor(mat[4] + xScale + 0.01);
- } else {
- tx = splashFloor(mat[4] + 0.01);
- tx2 = splashFloor(mat[4] + xScale - 0.01);
- }
- scaledWidth = abs(tx2 - tx) + 1;
- if (yScale >= 0) {
- ty = splashFloor(mat[5] - 0.01);
- ty2 = splashFloor(mat[5] + yScale + 0.01);
+ minorAxisZero = mat[1] == 0 && mat[2] == 0;
+
+ // scaling only
+ if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
+ x0 = imgCoordMungeLower(mat[4]);
+ y0 = imgCoordMungeLower(mat[5]);
+ x1 = imgCoordMungeUpper(mat[0] + mat[4]);
+ y1 = imgCoordMungeUpper(mat[3] + mat[5]);
+ // make sure narrow images cover at least one pixel
+ if (x0 == x1) {
+ ++x1;
+ }
+ if (y0 == y1) {
+ ++y1;
+ }
+ clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1);
+ opClipRes = clipRes;
+ if (clipRes != splashClipAllOutside) {
+ scaledWidth = x1 - x0;
+ scaledHeight = y1 - y0;
+ scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h,
+ scaledWidth, scaledHeight);
+ blitImage(scaledImg, srcAlpha, x0, y0, clipRes);
+ delete scaledImg;
+ }
+
+ // scaling plus vertical flip
+ } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) {
+ x0 = imgCoordMungeLower(mat[4]);
+ y0 = imgCoordMungeLower(mat[3] + mat[5]);
+ x1 = imgCoordMungeUpper(mat[0] + mat[4]);
+ y1 = imgCoordMungeUpper(mat[5]);
+ if (x0 == x1) {
+ if (mat[4] + mat[0] * 0.5 < x0) {
+ --x0;
+ } else {
+ ++x1;
+ }
+ }
+ if (y0 == y1) {
+ if (mat[5] + mat[1] * 0.5 < y0) {
+ --y0;
+ } else {
+ ++y1;
+ }
+ }
+ clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1);
+ opClipRes = clipRes;
+ if (clipRes != splashClipAllOutside) {
+ scaledWidth = x1 - x0;
+ scaledHeight = y1 - y0;
+ scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h,
+ scaledWidth, scaledHeight);
+ vertFlipImage(scaledImg, scaledWidth, scaledHeight, nComps);
+ blitImage(scaledImg, srcAlpha, x0, y0, clipRes);
+ delete scaledImg;
+ }
+
+ // all other cases
} else {
- ty = splashFloor(mat[5] + 0.01);
- ty2 = splashFloor(mat[5] + yScale - 0.01);
+ arbitraryTransformImage(src, srcData, srcMode, nComps, srcAlpha,
+ w, h, mat);
}
- scaledHeight = abs(ty2 - ty) + 1;
- xSign = (xScale < 0) ? -1 : 1;
- ySign = (yScale < 0) ? -1 : 1;
- yShear1 = (SplashCoord)xSign * yShear;
+
+ return splashOk;
+}
+
+void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha,
+ int srcWidth, int srcHeight,
+ SplashCoord *mat) {
+ SplashBitmap *scaledImg;
+ SplashClipResult clipRes, clipRes2;
+ SplashPipe pipe;
+ SplashColor pixel;
+ int scaledWidth, scaledHeight, t0, t1;
+ SplashCoord r00, r01, r10, r11, det, ir00, ir01, ir10, ir11;
+ SplashCoord vx[4], vy[4];
+ int xMin, yMin, xMax, yMax;
+ ImageSection section[3];
+ int nSections;
+ int y, xa, xb, x, i, xx, yy;
+
+ // compute the four vertices of the target quadrilateral
+ vx[0] = mat[4]; vy[0] = mat[5];
+ vx[1] = mat[2] + mat[4]; vy[1] = mat[3] + mat[5];
+ vx[2] = mat[0] + mat[2] + mat[4]; vy[2] = mat[1] + mat[3] + mat[5];
+ vx[3] = mat[0] + mat[4]; vy[3] = mat[1] + mat[5];
// clipping
- ulx1 = 0;
- uly1 = 0;
- urx1 = xSign * (scaledWidth - 1);
- ury1 = (int)(yShear * urx1);
- llx1 = splashRound(xShear * ySign * (scaledHeight - 1));
- lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1);
- lrx1 = xSign * (scaledWidth - 1) +
- splashRound(xShear * ySign * (scaledHeight - 1));
- lry1 = ySign * (scaledHeight - 1) + (int)(yShear * lrx1);
- if (rot) {
- ulx = tx + uly1; uly = ty - ulx1;
- urx = tx + ury1; ury = ty - urx1;
- llx = tx + lly1; lly = ty - llx1;
- lrx = tx + lry1; lry = ty - lrx1;
- } else {
- ulx = tx + ulx1; uly = ty + uly1;
- urx = tx + urx1; ury = ty + ury1;
- llx = tx + llx1; lly = ty + lly1;
- lrx = tx + lrx1; lry = ty + lry1;
- }
- xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
- : (llx < lrx) ? llx : lrx
- : (urx < llx) ? (urx < lrx) ? urx : lrx
- : (llx < lrx) ? llx : lrx;
- xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
- : (llx > lrx) ? llx : lrx
- : (urx > llx) ? (urx > lrx) ? urx : lrx
- : (llx > lrx) ? llx : lrx;
- yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
- : (lly < lry) ? lly : lry
- : (ury < lly) ? (ury < lry) ? ury : lry
- : (lly < lry) ? lly : lry;
- yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
- : (lly > lry) ? lly : lry
- : (ury > lly) ? (ury > lry) ? ury : lry
- : (lly > lry) ? lly : lry;
- clipRes = state->clip->testRect(xMin, yMin, xMax, yMax);
+ xMin = imgCoordMungeLower(vx[0]);
+ xMax = imgCoordMungeUpper(vx[0]);
+ yMin = imgCoordMungeLower(vy[0]);
+ yMax = imgCoordMungeUpper(vy[0]);
+ for (i = 1; i < 4; ++i) {
+ t0 = imgCoordMungeLower(vx[i]);
+ if (t0 < xMin) {
+ xMin = t0;
+ }
+ t0 = imgCoordMungeUpper(vx[i]);
+ if (t0 > xMax) {
+ xMax = t0;
+ }
+ t1 = imgCoordMungeLower(vy[i]);
+ if (t1 < yMin) {
+ yMin = t1;
+ }
+ t1 = imgCoordMungeUpper(vy[i]);
+ if (t1 > yMax) {
+ yMax = t1;
+ }
+ }
+ clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1);
opClipRes = clipRes;
if (clipRes == splashClipAllOutside) {
- return splashOk;
+ return;
}
- // compute Bresenham parameters for x and y scaling
- yp = h / scaledHeight;
- yq = h % scaledHeight;
- xp = w / scaledWidth;
- xq = w % scaledWidth;
-
- // allocate pixel buffers
- colorBuf = (SplashColorPtr)gmalloc((yp + 1) * w * nComps);
- if (srcAlpha) {
- alphaBuf = (Guchar *)gmalloc((yp + 1) * w);
+ // compute the scale factors
+ if (mat[0] >= 0) {
+ t0 = imgCoordMungeUpper(mat[0] + mat[4]) - imgCoordMungeLower(mat[4]);
+ } else {
+ t0 = imgCoordMungeUpper(mat[4]) - imgCoordMungeLower(mat[0] + mat[4]);
+ }
+ if (mat[1] >= 0) {
+ t1 = imgCoordMungeUpper(mat[1] + mat[5]) - imgCoordMungeLower(mat[5]);
+ } else {
+ t1 = imgCoordMungeUpper(mat[5]) - imgCoordMungeLower(mat[1] + mat[5]);
+ }
+ scaledWidth = t0 > t1 ? t0 : t1;
+ if (mat[2] >= 0) {
+ t0 = imgCoordMungeUpper(mat[2] + mat[4]) - imgCoordMungeLower(mat[4]);
+ } else {
+ t0 = imgCoordMungeUpper(mat[4]) - imgCoordMungeLower(mat[2] + mat[4]);
+ }
+ if (mat[3] >= 0) {
+ t1 = imgCoordMungeUpper(mat[3] + mat[5]) - imgCoordMungeLower(mat[5]);
} else {
- alphaBuf = NULL;
+ t1 = imgCoordMungeUpper(mat[5]) - imgCoordMungeLower(mat[3] + mat[5]);
+ }
+ scaledHeight = t0 > t1 ? t0 : t1;
+ if (scaledWidth == 0) {
+ scaledWidth = 1;
+ }
+ if (scaledHeight == 0) {
+ scaledHeight = 1;
}
- pixAcc0 = pixAcc1 = pixAcc2 = 0; // make gcc happy
-#if SPLASH_CMYK
- pixAcc3 = 0; // make gcc happy
-#endif
+ // compute the inverse transform (after scaling) matrix
+ r00 = mat[0] / scaledWidth;
+ r01 = mat[1] / scaledWidth;
+ r10 = mat[2] / scaledHeight;
+ r11 = mat[3] / scaledHeight;
+ det = r00 * r11 - r01 * r10;
+ if (splashAbs(det) < 1e-6) {
+ // this should be caught by the singular matrix check in drawImage
+ return;
+ }
+ ir00 = r11 / det;
+ ir01 = -r01 / det;
+ ir10 = -r10 / det;
+ ir11 = r00 / det;
+
+ // scale the input image
+ scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha,
+ srcWidth, srcHeight, scaledWidth, scaledHeight);
+
+ // construct the three sections
+ i = 0;
+ if (vy[1] < vy[i]) {
+ i = 1;
+ }
+ if (vy[2] < vy[i]) {
+ i = 2;
+ }
+ if (vy[3] < vy[i]) {
+ i = 3;
+ }
+ // NB: if using fixed point, 0.000001 will be truncated to zero,
+ // so these two comparisons must be <=, not <
+ if (splashAbs(vy[i] - vy[(i-1) & 3]) <= 0.000001 &&
+ vy[(i-1) & 3] < vy[(i+1) & 3]) {
+ i = (i-1) & 3;
+ }
+ if (splashAbs(vy[i] - vy[(i+1) & 3]) <= 0.000001) {
+ section[0].y0 = imgCoordMungeLower(vy[i]);
+ section[0].y1 = imgCoordMungeUpper(vy[(i+2) & 3]) - 1;
+ if (vx[i] < vx[(i+1) & 3]) {
+ section[0].ia0 = i;
+ section[0].ia1 = (i+3) & 3;
+ section[0].ib0 = (i+1) & 3;
+ section[0].ib1 = (i+2) & 3;
+ } else {
+ section[0].ia0 = (i+1) & 3;
+ section[0].ia1 = (i+2) & 3;
+ section[0].ib0 = i;
+ section[0].ib1 = (i+3) & 3;
+ }
+ nSections = 1;
+ } else {
+ section[0].y0 = imgCoordMungeLower(vy[i]);
+ section[2].y1 = imgCoordMungeUpper(vy[(i+2) & 3]) - 1;
+ section[0].ia0 = section[0].ib0 = i;
+ section[2].ia1 = section[2].ib1 = (i+2) & 3;
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[0].ia1 = section[2].ia0 = (i+1) & 3;
+ section[0].ib1 = section[2].ib0 = (i+3) & 3;
+ } else {
+ section[0].ia1 = section[2].ia0 = (i+3) & 3;
+ section[0].ib1 = section[2].ib0 = (i+1) & 3;
+ }
+ if (vy[(i+1) & 3] < vy[(i+3) & 3]) {
+ section[1].y0 = imgCoordMungeLower(vy[(i+1) & 3]);
+ section[2].y0 = imgCoordMungeUpper(vy[(i+3) & 3]);
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[1].ia0 = (i+1) & 3;
+ section[1].ia1 = (i+2) & 3;
+ section[1].ib0 = i;
+ section[1].ib1 = (i+3) & 3;
+ } else {
+ section[1].ia0 = i;
+ section[1].ia1 = (i+3) & 3;
+ section[1].ib0 = (i+1) & 3;
+ section[1].ib1 = (i+2) & 3;
+ }
+ } else {
+ section[1].y0 = imgCoordMungeLower(vy[(i+3) & 3]);
+ section[2].y0 = imgCoordMungeUpper(vy[(i+1) & 3]);
+ if (vx[(i+1) & 3] < vx[(i+3) & 3]) {
+ section[1].ia0 = i;
+ section[1].ia1 = (i+1) & 3;
+ section[1].ib0 = (i+3) & 3;
+ section[1].ib1 = (i+2) & 3;
+ } else {
+ section[1].ia0 = (i+3) & 3;
+ section[1].ia1 = (i+2) & 3;
+ section[1].ib0 = i;
+ section[1].ib1 = (i+1) & 3;
+ }
+ }
+ section[0].y1 = section[1].y0 - 1;
+ section[1].y1 = section[2].y0 - 1;
+ nSections = 3;
+ }
+ for (i = 0; i < nSections; ++i) {
+ section[i].xa0 = vx[section[i].ia0];
+ section[i].ya0 = vy[section[i].ia0];
+ section[i].xa1 = vx[section[i].ia1];
+ section[i].ya1 = vy[section[i].ia1];
+ section[i].xb0 = vx[section[i].ib0];
+ section[i].yb0 = vy[section[i].ib0];
+ section[i].xb1 = vx[section[i].ib1];
+ section[i].yb1 = vy[section[i].ib1];
+ section[i].dxdya = (section[i].xa1 - section[i].xa0) /
+ (section[i].ya1 - section[i].ya0);
+ section[i].dxdyb = (section[i].xb1 - section[i].xb0) /
+ (section[i].yb1 - section[i].yb0);
+ }
// initialize the pixel pipe
- pipeInit(&pipe, 0, 0, NULL, pix, state->fillAlpha,
+ pipeInit(&pipe, 0, 0, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255),
srcAlpha || (vectorAntialias && clipRes != splashClipAllInside),
gFalse);
if (vectorAntialias) {
drawAAPixelInit();
}
- if (srcAlpha) {
-
- // init y scale Bresenham
- yt = 0;
- lastYStep = 1;
-
- for (y = 0; y < scaledHeight; ++y) {
+ // make sure narrow images cover at least one pixel
+ if (nSections == 1) {
+ if (section[0].y0 == section[0].y1) {
+ ++section[0].y1;
+ clipRes = opClipRes = splashClipPartial;
+ }
+ } else {
+ if (section[0].y0 == section[2].y1) {
+ ++section[1].y1;
+ clipRes = opClipRes = splashClipPartial;
+ }
+ }
- // y scale Bresenham
- yStep = yp;
- yt += yq;
- if (yt >= scaledHeight) {
- yt -= scaledHeight;
- ++yStep;
- }
-
- // read row(s) from image
- n = (yp > 0) ? yStep : lastYStep;
- if (n > 0) {
- p = colorBuf;
- q = alphaBuf;
- for (i = 0; i < n; ++i) {
- (*src)(srcData, p, q);
- p += w * nComps;
- q += w;
- }
- }
- lastYStep = yStep;
-
- // loop-invariant constants
- k1 = splashRound(xShear * ySign * y);
-
- // clipping test
- if (clipRes != splashClipAllInside &&
- !rot &&
- (int)(yShear * k1) ==
- (int)(yShear * (xSign * (scaledWidth - 1) + k1))) {
- if (xSign > 0) {
- spanXMin = tx + k1;
- spanXMax = spanXMin + (scaledWidth - 1);
+ // scan all pixels inside the target region
+ for (i = 0; i < nSections; ++i) {
+ for (y = section[i].y0; y <= section[i].y1; ++y) {
+ xa = imgCoordMungeLower(section[i].xa0 +
+ ((SplashCoord)y + 0.5 - section[i].ya0) *
+ section[i].dxdya);
+ xb = imgCoordMungeUpper(section[i].xb0 +
+ ((SplashCoord)y + 0.5 - section[i].yb0) *
+ section[i].dxdyb);
+ // make sure narrow images cover at least one pixel
+ if (xa == xb) {
+ ++xb;
+ }
+ if (clipRes != splashClipAllInside) {
+ clipRes2 = state->clip->testSpan(xa, xb - 1, y);
+ } else {
+ clipRes2 = clipRes;
+ }
+ for (x = xa; x < xb; ++x) {
+ // map (x+0.5, y+0.5) back to the scaled image
+ xx = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir00 +
+ ((SplashCoord)y + 0.5 - mat[5]) * ir10);
+ yy = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir01 +
+ ((SplashCoord)y + 0.5 - mat[5]) * ir11);
+ // xx should always be within bounds, but floating point
+ // inaccuracy can cause problems
+ if (xx < 0) {
+ xx = 0;
+ } else if (xx >= scaledWidth) {
+ xx = scaledWidth - 1;
+ }
+ if (yy < 0) {
+ yy = 0;
+ } else if (yy >= scaledHeight) {
+ yy = scaledHeight - 1;
+ }
+ scaledImg->getPixel(xx, yy, pixel);
+ if (srcAlpha) {
+ pipe.shape = scaledImg->alpha[yy * scaledWidth + xx];
} else {
- spanXMax = tx + k1;
- spanXMin = spanXMax - (scaledWidth - 1);
+ pipe.shape = 255;
}
- spanY = ty + ySign * y + (int)(yShear * k1);
- clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY);
- if (clipRes2 == splashClipAllOutside) {
- continue;
+ if (vectorAntialias && clipRes2 != splashClipAllInside) {
+ drawAAPixel(&pipe, x, y);
+ } else {
+ drawPixel(&pipe, x, y, clipRes2 == splashClipAllInside);
}
- } else {
- clipRes2 = clipRes;
}
+ }
+ }
- // init x scale Bresenham
- xt = 0;
- xSrc = 0;
+ delete scaledImg;
+}
- // x shear
- x1 = k1;
+// Scale an image into a SplashBitmap.
+SplashBitmap *Splash::scaleImage(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight) {
+ SplashBitmap *dest;
+
+ dest = new SplashBitmap(scaledWidth, scaledHeight, 1, srcMode, srcAlpha);
+ if (scaledHeight < srcHeight) {
+ if (scaledWidth < srcWidth) {
+ scaleImageYdXd(src, srcData, srcMode, nComps, srcAlpha,
+ srcWidth, srcHeight, scaledWidth, scaledHeight, dest);
+ } else {
+ scaleImageYdXu(src, srcData, srcMode, nComps, srcAlpha,
+ srcWidth, srcHeight, scaledWidth, scaledHeight, dest);
+ }
+ } else {
+ if (scaledWidth < srcWidth) {
+ scaleImageYuXd(src, srcData, srcMode, nComps, srcAlpha,
+ srcWidth, srcHeight, scaledWidth, scaledHeight, dest);
+ } else {
+ scaleImageYuXu(src, srcData, srcMode, nComps, srcAlpha,
+ srcWidth, srcHeight, scaledWidth, scaledHeight, dest);
+ }
+ }
+ return dest;
+}
- // y shear
- y1 = (SplashCoord)ySign * y + yShear * x1;
- // this is a kludge: if yShear1 is negative, then (int)y1 would
- // change immediately after the first pixel, which is not what
- // we want
- if (yShear1 < 0) {
- y1 += 0.999;
- }
+void Splash::scaleImageYdXd(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf, *alphaLineBuf;
+ Guint *pixBuf, *alphaPixBuf;
+ Guint pix0, pix1, pix2;
+#if SPLASH_CMYK
+ Guint pix3;
+#endif
+ Guint alpha;
+ Guchar *destPtr, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx, xxa, d, d0, d1;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+
+ // Bresenham parameters for x scale
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmallocn(srcWidth, nComps);
+ pixBuf = (Guint *)gmallocn(srcWidth, nComps * sizeof(int));
+ if (srcAlpha) {
+ alphaLineBuf = (Guchar *)gmalloc(srcWidth);
+ alphaPixBuf = (Guint *)gmallocn(srcWidth, sizeof(int));
+ } else {
+ alphaLineBuf = NULL;
+ alphaPixBuf = NULL;
+ }
- // loop-invariant constants
- n = yStep > 0 ? yStep : 1;
+ // init y scale Bresenham
+ yt = 0;
- switch (srcMode) {
+ destPtr = dest->data;
+ destAlphaPtr = dest->alpha;
+ for (y = 0; y < scaledHeight; ++y) {
- case splashModeMono1:
- case splashModeMono8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
+ // y scale Bresenham
+ if ((yt += yq) >= scaledHeight) {
+ yt -= scaledHeight;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
+ }
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
- }
+ // read rows from image
+ memset(pixBuf, 0, srcWidth * nComps * sizeof(int));
+ if (srcAlpha) {
+ memset(alphaPixBuf, 0, srcWidth * sizeof(int));
+ }
+ for (i = 0; i < yStep; ++i) {
+ (*src)(srcData, lineBuf, alphaLineBuf);
+ for (j = 0; j < srcWidth * nComps; ++j) {
+ pixBuf[j] += lineBuf[j];
+ }
+ if (srcAlpha) {
+ for (j = 0; j < srcWidth; ++j) {
+ alphaPixBuf[j] += alphaLineBuf[j];
+ }
+ }
+ }
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- alphaAcc = 0;
- p = colorBuf + xSrc;
- q = alphaBuf + xSrc;
- pixAcc0 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- alphaAcc += *q++;
- }
- p += w - m;
- q += w - m;
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
- alphaMul = pixMul * (1.0 / 255.0);
- alpha = (SplashCoord)alphaAcc * alphaMul;
+ // init x scale Bresenham
+ xt = 0;
+ d0 = (1 << 23) / (yStep * xp);
+ d1 = (1 << 23) / (yStep * (xp + 1));
- if (alpha > 0) {
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
+ xx = xxa = 0;
+ for (x = 0; x < scaledWidth; ++x) {
- // set pixel
- pipe.shape = alpha;
- if (vectorAntialias && clipRes != splashClipAllInside) {
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
- }
+ // x scale Bresenham
+ if ((xt += xq) >= scaledWidth) {
+ xt -= scaledWidth;
+ xStep = xp + 1;
+ d = d1;
+ } else {
+ xStep = xp;
+ d = d0;
+ }
- // x scale Bresenham
- xSrc += xStep;
+ switch (srcMode) {
- // x shear
- x1 += xSign;
+ case splashModeMono8:
- // y shear
- y1 += yShear1;
+ // compute the final pixel
+ pix0 = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix0 += pixBuf[xx++];
}
+ // pix / xStep * yStep
+ pix0 = (pix0 * d) >> 23;
+
+ // store the pixel
+ *destPtr++ = (Guchar)pix0;
break;
case splashModeRGB8:
- case splashModeBGR8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
-
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
- }
-
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- alphaAcc = 0;
- p = colorBuf + xSrc * 3;
- q = alphaBuf + xSrc;
- pixAcc0 = pixAcc1 = pixAcc2 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- pixAcc1 += *p++;
- pixAcc2 += *p++;
- alphaAcc += *q++;
- }
- p += 3 * (w - m);
- q += w - m;
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
- alphaMul = pixMul * (1.0 / 255.0);
- alpha = (SplashCoord)alphaAcc * alphaMul;
-
- if (alpha > 0) {
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
- pix[1] = (int)((SplashCoord)pixAcc1 * pixMul);
- pix[2] = (int)((SplashCoord)pixAcc2 * pixMul);
-
- // set pixel
- pipe.shape = alpha;
- if (vectorAntialias && clipRes != splashClipAllInside) {
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
- }
- // x scale Bresenham
- xSrc += xStep;
+ // compute the final pixel
+ pix0 = pix1 = pix2 = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix0 += pixBuf[xx];
+ pix1 += pixBuf[xx+1];
+ pix2 += pixBuf[xx+2];
+ xx += 3;
+ }
+ // pix / xStep * yStep
+ pix0 = (pix0 * d) >> 23;
+ pix1 = (pix1 * d) >> 23;
+ pix2 = (pix2 * d) >> 23;
+
+ // store the pixel
+ *destPtr++ = (Guchar)pix0;
+ *destPtr++ = (Guchar)pix1;
+ *destPtr++ = (Guchar)pix2;
+ break;
- // x shear
- x1 += xSign;
+ case splashModeBGR8:
- // y shear
- y1 += yShear1;
+ // compute the final pixel
+ pix0 = pix1 = pix2 = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix0 += pixBuf[xx];
+ pix1 += pixBuf[xx+1];
+ pix2 += pixBuf[xx+2];
+ xx += 3;
}
+ // pix / xStep * yStep
+ pix0 = (pix0 * d) >> 23;
+ pix1 = (pix1 * d) >> 23;
+ pix2 = (pix2 * d) >> 23;
+
+ // store the pixel
+ *destPtr++ = (Guchar)pix2;
+ *destPtr++ = (Guchar)pix1;
+ *destPtr++ = (Guchar)pix0;
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
-
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
- }
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- alphaAcc = 0;
- p = colorBuf + xSrc * 4;
- q = alphaBuf + xSrc;
- pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- pixAcc1 += *p++;
- pixAcc2 += *p++;
- pixAcc3 += *p++;
- alphaAcc += *q++;
- }
- p += 4 * (w - m);
- q += w - m;
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
- alphaMul = pixMul * (1.0 / 255.0);
- alpha = (SplashCoord)alphaAcc * alphaMul;
-
- if (alpha > 0) {
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
- pix[1] = (int)((SplashCoord)pixAcc1 * pixMul);
- pix[2] = (int)((SplashCoord)pixAcc2 * pixMul);
- pix[3] = (int)((SplashCoord)pixAcc3 * pixMul);
-
- // set pixel
- pipe.shape = alpha;
- if (vectorAntialias && clipRes != splashClipAllInside) {
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
- }
+ // compute the final pixel
+ pix0 = pix1 = pix2 = pix3 = 0;
+ for (i = 0; i < xStep; ++i) {
+ pix0 += pixBuf[xx];
+ pix1 += pixBuf[xx+1];
+ pix2 += pixBuf[xx+2];
+ pix3 += pixBuf[xx+3];
+ xx += 4;
+ }
+ // pix / xStep * yStep
+ pix0 = (pix0 * d) >> 23;
+ pix1 = (pix1 * d) >> 23;
+ pix2 = (pix2 * d) >> 23;
+ pix3 = (pix3 * d) >> 23;
+
+ // store the pixel
+ *destPtr++ = (Guchar)pix0;
+ *destPtr++ = (Guchar)pix1;
+ *destPtr++ = (Guchar)pix2;
+ *destPtr++ = (Guchar)pix3;
+ break;
+#endif
- // x scale Bresenham
- xSrc += xStep;
- // x shear
- x1 += xSign;
+ case splashModeMono1: // mono1 is not allowed
+ default:
+ break;
+ }
- // y shear
- y1 += yShear1;
+ // process alpha
+ if (srcAlpha) {
+ alpha = 0;
+ for (i = 0; i < xStep; ++i, ++xxa) {
+ alpha += alphaPixBuf[xxa];
}
- break;
-#endif // SPLASH_CMYK
+ // alpha / xStep * yStep
+ alpha = (alpha * d) >> 23;
+ *destAlphaPtr++ = (Guchar)alpha;
}
}
+ }
+ gfree(alphaPixBuf);
+ gfree(alphaLineBuf);
+ gfree(pixBuf);
+ gfree(lineBuf);
+}
+
+void Splash::scaleImageYdXu(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf, *alphaLineBuf;
+ Guint *pixBuf, *alphaPixBuf;
+ Guint pix[splashMaxColorComps];
+ Guint alpha;
+ Guchar *destPtr, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, d;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = srcHeight / scaledHeight;
+ yq = srcHeight % scaledHeight;
+
+ // Bresenham parameters for x scale
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmallocn(srcWidth, nComps);
+ pixBuf = (Guint *)gmallocn(srcWidth, nComps * sizeof(int));
+ if (srcAlpha) {
+ alphaLineBuf = (Guchar *)gmalloc(srcWidth);
+ alphaPixBuf = (Guint *)gmallocn(srcWidth, sizeof(int));
} else {
+ alphaLineBuf = NULL;
+ alphaPixBuf = NULL;
+ }
- // init y scale Bresenham
- yt = 0;
- lastYStep = 1;
+ // init y scale Bresenham
+ yt = 0;
- for (y = 0; y < scaledHeight; ++y) {
+ destPtr = dest->data;
+ destAlphaPtr = dest->alpha;
+ for (y = 0; y < scaledHeight; ++y) {
- // y scale Bresenham
+ // y scale Bresenham
+ if ((yt += yq) >= scaledHeight) {
+ yt -= scaledHeight;
+ yStep = yp + 1;
+ } else {
yStep = yp;
- yt += yq;
- if (yt >= scaledHeight) {
- yt -= scaledHeight;
- ++yStep;
- }
-
- // read row(s) from image
- n = (yp > 0) ? yStep : lastYStep;
- if (n > 0) {
- p = colorBuf;
- for (i = 0; i < n; ++i) {
- (*src)(srcData, p, NULL);
- p += w * nComps;
- }
- }
- lastYStep = yStep;
-
- // loop-invariant constants
- k1 = splashRound(xShear * ySign * y);
-
- // clipping test
- if (clipRes != splashClipAllInside &&
- !rot &&
- (int)(yShear * k1) ==
- (int)(yShear * (xSign * (scaledWidth - 1) + k1))) {
- if (xSign > 0) {
- spanXMin = tx + k1;
- spanXMax = spanXMin + (scaledWidth - 1);
- } else {
- spanXMax = tx + k1;
- spanXMin = spanXMax - (scaledWidth - 1);
- }
- spanY = ty + ySign * y + (int)(yShear * k1);
- clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY);
- if (clipRes2 == splashClipAllOutside) {
- continue;
+ }
+
+ // read rows from image
+ memset(pixBuf, 0, srcWidth * nComps * sizeof(int));
+ if (srcAlpha) {
+ memset(alphaPixBuf, 0, srcWidth * sizeof(int));
+ }
+ for (i = 0; i < yStep; ++i) {
+ (*src)(srcData, lineBuf, alphaLineBuf);
+ for (j = 0; j < srcWidth * nComps; ++j) {
+ pixBuf[j] += lineBuf[j];
+ }
+ if (srcAlpha) {
+ for (j = 0; j < srcWidth; ++j) {
+ alphaPixBuf[j] += alphaLineBuf[j];
}
- } else {
- clipRes2 = clipRes;
}
+ }
- // init x scale Bresenham
- xt = 0;
- xSrc = 0;
+ // init x scale Bresenham
+ xt = 0;
+ d = (1 << 23) / yStep;
- // x shear
- x1 = k1;
+ for (x = 0; x < srcWidth; ++x) {
- // y shear
- y1 = (SplashCoord)ySign * y + yShear * x1;
- // this is a kludge: if yShear1 is negative, then (int)y1 would
- // change immediately after the first pixel, which is not what
- // we want
- if (yShear1 < 0) {
- y1 += 0.999;
+ // x scale Bresenham
+ if ((xt += xq) >= srcWidth) {
+ xt -= srcWidth;
+ xStep = xp + 1;
+ } else {
+ xStep = xp;
}
- // loop-invariant constants
- n = yStep > 0 ? yStep : 1;
+ // compute the final pixel
+ for (i = 0; i < nComps; ++i) {
+ // pixBuf[] / yStep
+ pix[i] = (pixBuf[x * nComps + i] * d) >> 23;
+ }
+ // store the pixel
switch (srcMode) {
-
- case splashModeMono1:
+ case splashModeMono1: // mono1 is not allowed
+ break;
case splashModeMono8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = (Guchar)pix[0];
+ }
+ break;
+ case splashModeRGB8:
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ }
+ break;
+ case splashModeBGR8:
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[0];
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[3];
+ }
+ break;
+#endif
+ }
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
- }
+ // process alpha
+ if (srcAlpha) {
+ // alphaPixBuf[] / yStep
+ alpha = (alphaPixBuf[x] * d) >> 23;
+ for (i = 0; i < xStep; ++i) {
+ *destAlphaPtr++ = (Guchar)alpha;
+ }
+ }
+ }
+ }
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- p = colorBuf + xSrc;
- pixAcc0 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- }
- p += w - m;
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
+ gfree(alphaPixBuf);
+ gfree(alphaLineBuf);
+ gfree(pixBuf);
+ gfree(lineBuf);
+}
+
+void Splash::scaleImageYuXd(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf, *alphaLineBuf;
+ Guint pix[splashMaxColorComps];
+ Guint alpha;
+ Guchar *destPtr0, *destPtr, *destAlphaPtr0, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx, xxa, d, d0, d1;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
+
+ // Bresenham parameters for x scale
+ xp = srcWidth / scaledWidth;
+ xq = srcWidth % scaledWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmallocn(srcWidth, nComps);
+ if (srcAlpha) {
+ alphaLineBuf = (Guchar *)gmalloc(srcWidth);
+ } else {
+ alphaLineBuf = NULL;
+ }
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
+ // init y scale Bresenham
+ yt = 0;
- // set pixel
- if (vectorAntialias && clipRes != splashClipAllInside) {
- pipe.shape = (SplashCoord)1;
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
+ destPtr0 = dest->data;
+ destAlphaPtr0 = dest->alpha;
+ for (y = 0; y < srcHeight; ++y) {
- // x scale Bresenham
- xSrc += xStep;
+ // y scale Bresenham
+ if ((yt += yq) >= srcHeight) {
+ yt -= srcHeight;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
+ }
+
+ // read row from image
+ (*src)(srcData, lineBuf, alphaLineBuf);
+
+ // init x scale Bresenham
+ xt = 0;
+ d0 = (1 << 23) / xp;
+ d1 = (1 << 23) / (xp + 1);
+
+ xx = xxa = 0;
+ for (x = 0; x < scaledWidth; ++x) {
- // x shear
- x1 += xSign;
+ // x scale Bresenham
+ if ((xt += xq) >= scaledWidth) {
+ xt -= scaledWidth;
+ xStep = xp + 1;
+ d = d1;
+ } else {
+ xStep = xp;
+ d = d0;
+ }
- // y shear
- y1 += yShear1;
+ // compute the final pixel
+ for (i = 0; i < nComps; ++i) {
+ pix[i] = 0;
+ }
+ for (i = 0; i < xStep; ++i) {
+ for (j = 0; j < nComps; ++j, ++xx) {
+ pix[j] += lineBuf[xx];
}
- break;
+ }
+ for (i = 0; i < nComps; ++i) {
+ // pix[] / xStep
+ pix[i] = (pix[i] * d) >> 23;
+ }
+ // store the pixel
+ switch (srcMode) {
+ case splashModeMono1: // mono1 is not allowed
+ break;
+ case splashModeMono8:
+ for (i = 0; i < yStep; ++i) {
+ destPtr = destPtr0 + (i * scaledWidth + x) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ }
+ break;
case splashModeRGB8:
+ for (i = 0; i < yStep; ++i) {
+ destPtr = destPtr0 + (i * scaledWidth + x) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ }
+ break;
case splashModeBGR8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
+ for (i = 0; i < yStep; ++i) {
+ destPtr = destPtr0 + (i * scaledWidth + x) * nComps;
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[0];
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (i = 0; i < yStep; ++i) {
+ destPtr = destPtr0 + (i * scaledWidth + x) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[3];
+ }
+ break;
+#endif
+ }
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
- }
+ // process alpha
+ if (srcAlpha) {
+ alpha = 0;
+ for (i = 0; i < xStep; ++i, ++xxa) {
+ alpha += alphaLineBuf[xxa];
+ }
+ // alpha / xStep
+ alpha = (alpha * d) >> 23;
+ for (i = 0; i < yStep; ++i) {
+ destAlphaPtr = destAlphaPtr0 + i * scaledWidth + x;
+ *destAlphaPtr = (Guchar)alpha;
+ }
+ }
+ }
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- p = colorBuf + xSrc * 3;
- pixAcc0 = pixAcc1 = pixAcc2 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- pixAcc1 += *p++;
- pixAcc2 += *p++;
- }
- p += 3 * (w - m);
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
+ destPtr0 += yStep * scaledWidth * nComps;
+ if (srcAlpha) {
+ destAlphaPtr0 += yStep * scaledWidth;
+ }
+ }
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
- pix[1] = (int)((SplashCoord)pixAcc1 * pixMul);
- pix[2] = (int)((SplashCoord)pixAcc2 * pixMul);
+ gfree(alphaLineBuf);
+ gfree(lineBuf);
+}
- // set pixel
- if (vectorAntialias && clipRes != splashClipAllInside) {
- pipe.shape = (SplashCoord)1;
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
+void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest) {
+ Guchar *lineBuf, *alphaLineBuf;
+ Guint pix[splashMaxColorComps];
+ Guint alpha;
+ Guchar *destPtr0, *destPtr, *destAlphaPtr0, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
+ int i, j;
+
+ // Bresenham parameters for y scale
+ yp = scaledHeight / srcHeight;
+ yq = scaledHeight % srcHeight;
+
+ // Bresenham parameters for x scale
+ xp = scaledWidth / srcWidth;
+ xq = scaledWidth % srcWidth;
+
+ // allocate buffers
+ lineBuf = (Guchar *)gmallocn(srcWidth, nComps);
+ if (srcAlpha) {
+ alphaLineBuf = (Guchar *)gmalloc(srcWidth);
+ } else {
+ alphaLineBuf = NULL;
+ }
+
+ // init y scale Bresenham
+ yt = 0;
+
+ destPtr0 = dest->data;
+ destAlphaPtr0 = dest->alpha;
+ for (y = 0; y < srcHeight; ++y) {
+
+ // y scale Bresenham
+ if ((yt += yq) >= srcHeight) {
+ yt -= srcHeight;
+ yStep = yp + 1;
+ } else {
+ yStep = yp;
+ }
+
+ // read row from image
+ (*src)(srcData, lineBuf, alphaLineBuf);
+
+ // init x scale Bresenham
+ xt = 0;
- // x scale Bresenham
- xSrc += xStep;
+ xx = 0;
+ for (x = 0; x < srcWidth; ++x) {
- // x shear
- x1 += xSign;
+ // x scale Bresenham
+ if ((xt += xq) >= srcWidth) {
+ xt -= srcWidth;
+ xStep = xp + 1;
+ } else {
+ xStep = xp;
+ }
- // y shear
- y1 += yShear1;
+ // compute the final pixel
+ for (i = 0; i < nComps; ++i) {
+ pix[i] = lineBuf[x * nComps + i];
+ }
+
+ // store the pixel
+ switch (srcMode) {
+ case splashModeMono1: // mono1 is not allowed
+ break;
+ case splashModeMono8:
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ }
+ }
+ break;
+ case splashModeRGB8:
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ }
+ }
+ break;
+ case splashModeBGR8:
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[0];
+ }
}
break;
-
#if SPLASH_CMYK
case splashModeCMYK8:
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
+ *destPtr++ = (Guchar)pix[0];
+ *destPtr++ = (Guchar)pix[1];
+ *destPtr++ = (Guchar)pix[2];
+ *destPtr++ = (Guchar)pix[3];
}
+ }
+ break;
+#endif
+ }
- // rotation
- if (rot) {
- x2 = (int)y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = (int)y1;
+ // process alpha
+ if (srcAlpha) {
+ alpha = alphaLineBuf[x];
+ for (i = 0; i < yStep; ++i) {
+ for (j = 0; j < xStep; ++j) {
+ destAlphaPtr = destAlphaPtr0 + i * scaledWidth + xx + j;
+ *destAlphaPtr = (Guchar)alpha;
}
+ }
+ }
- // compute the filtered pixel at (x,y) after the x and y scaling
- // operations
- m = xStep > 0 ? xStep : 1;
- p = colorBuf + xSrc * 4;
- pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- pixAcc0 += *p++;
- pixAcc1 += *p++;
- pixAcc2 += *p++;
- pixAcc3 += *p++;
- }
- p += 4 * (w - m);
- }
- pixMul = (SplashCoord)1 / (SplashCoord)(n * m);
+ xx += xStep;
+ }
- pix[0] = (int)((SplashCoord)pixAcc0 * pixMul);
- pix[1] = (int)((SplashCoord)pixAcc1 * pixMul);
- pix[2] = (int)((SplashCoord)pixAcc2 * pixMul);
- pix[3] = (int)((SplashCoord)pixAcc3 * pixMul);
+ destPtr0 += yStep * scaledWidth * nComps;
+ if (srcAlpha) {
+ destAlphaPtr0 += yStep * scaledWidth;
+ }
+ }
- // set pixel
- if (vectorAntialias && clipRes != splashClipAllInside) {
- pipe.shape = (SplashCoord)1;
- drawAAPixel(&pipe, tx + x2, ty + y2);
- } else {
- drawPixel(&pipe, tx + x2, ty + y2,
- clipRes2 == splashClipAllInside);
- }
+ gfree(alphaLineBuf);
+ gfree(lineBuf);
+}
- // x scale Bresenham
- xSrc += xStep;
+void Splash::vertFlipImage(SplashBitmap *img, int width, int height,
+ int nComps) {
+ Guchar *lineBuf;
+ Guchar *p0, *p1;
+ int w;
+
+ w = width * nComps;
+ lineBuf = (Guchar *)gmalloc(w);
+ for (p0 = img->data, p1 = img->data + (height - 1) * w;
+ p0 < p1;
+ p0 += w, p1 -= w) {
+ memcpy(lineBuf, p0, w);
+ memcpy(p0, p1, w);
+ memcpy(p1, lineBuf, w);
+ }
+ if (img->alpha) {
+ for (p0 = img->alpha, p1 = img->alpha + (height - 1) * width;
+ p0 < p1;
+ p0 += width, p1 -= width) {
+ memcpy(lineBuf, p0, width);
+ memcpy(p0, p1, width);
+ memcpy(p1, lineBuf, width);
+ }
+ }
+ gfree(lineBuf);
+}
+
+void Splash::blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest,
+ SplashClipResult clipRes) {
+ SplashPipe pipe;
+ SplashColor pixel;
+ Guchar *ap;
+ int w, h, x0, y0, x1, y1, x, y;
- // x shear
- x1 += xSign;
+ // split the image into clipped and unclipped regions
+ w = src->getWidth();
+ h = src->getHeight();
+ if (clipRes == splashClipAllInside) {
+ x0 = 0;
+ y0 = 0;
+ x1 = w;
+ y1 = h;
+ } else {
+ if (state->clip->getNumPaths()) {
+ x0 = x1 = w;
+ y0 = y1 = h;
+ } else {
+ if ((x0 = splashCeil(state->clip->getXMin()) - xDest) < 0) {
+ x0 = 0;
+ }
+ if ((y0 = splashCeil(state->clip->getYMin()) - yDest) < 0) {
+ y0 = 0;
+ }
+ if ((x1 = splashFloor(state->clip->getXMax()) - xDest) > w) {
+ x1 = w;
+ }
+ if (x1 < x0) {
+ x1 = x0;
+ }
+ if ((y1 = splashFloor(state->clip->getYMax()) - yDest) > h) {
+ y1 = h;
+ }
+ if (y1 < y0) {
+ y1 = y0;
+ }
+ }
+ }
- // y shear
- y1 += yShear1;
+ // draw the unclipped region
+ if (x0 < w && y0 < h && x0 < x1 && y0 < y1) {
+ pipeInit(&pipe, xDest + x0, yDest + y0, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255), srcAlpha, gFalse);
+ if (srcAlpha) {
+ for (y = y0; y < y1; ++y) {
+ pipeSetXY(&pipe, xDest + x0, yDest + y);
+ ap = src->getAlphaPtr() + y * w + x0;
+ for (x = x0; x < x1; ++x) {
+ src->getPixel(x, y, pixel);
+ pipe.shape = *ap++;
+ (this->*pipe.run)(&pipe);
+ }
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ pipeSetXY(&pipe, xDest + x0, yDest + y);
+ for (x = x0; x < x1; ++x) {
+ src->getPixel(x, y, pixel);
+ (this->*pipe.run)(&pipe);
}
- break;
-#endif // SPLASH_CMYK
}
}
+ updateModX(xDest + x0);
+ updateModX(xDest + x1 - 1);
+ updateModY(yDest + y0);
+ updateModY(yDest + y1 - 1);
+ }
+ // draw the clipped regions
+ if (y0 > 0) {
+ blitImageClipped(src, srcAlpha, 0, 0, xDest, yDest, w, y0);
+ }
+ if (y1 < h) {
+ blitImageClipped(src, srcAlpha, 0, y1, xDest, yDest + y1, w, h - y1);
+ }
+ if (x0 > 0 && y0 < y1) {
+ blitImageClipped(src, srcAlpha, 0, y0, xDest, yDest + y0, x0, y1 - y0);
}
+ if (x1 < w && y0 < y1) {
+ blitImageClipped(src, srcAlpha, x1, y0, xDest + x1, yDest + y0,
+ w - x1, y1 - y0);
+ }
+}
- gfree(colorBuf);
- gfree(alphaBuf);
+void Splash::blitImageClipped(SplashBitmap *src, GBool srcAlpha,
+ int xSrc, int ySrc, int xDest, int yDest,
+ int w, int h) {
+ SplashPipe pipe;
+ SplashColor pixel;
+ Guchar *ap;
+ int x, y;
- return splashOk;
+ if (vectorAntialias) {
+ pipeInit(&pipe, xDest, yDest, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
+ drawAAPixelInit();
+ if (srcAlpha) {
+ for (y = 0; y < h; ++y) {
+ ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc;
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ pipe.shape = *ap++;
+ drawAAPixel(&pipe, xDest + x, yDest + y);
+ }
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ pipe.shape = 255;
+ drawAAPixel(&pipe, xDest + x, yDest + y);
+ }
+ }
+ }
+ } else {
+ pipeInit(&pipe, xDest, yDest, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255), srcAlpha, gFalse);
+ if (srcAlpha) {
+ for (y = 0; y < h; ++y) {
+ ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc;
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ if (state->clip->test(xDest + x, yDest + y)) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ pipe.shape = *ap++;
+ (this->*pipe.run)(&pipe);
+ updateModX(xDest + x);
+ updateModY(yDest + y);
+ } else {
+ pipeIncX(&pipe);
+ ++ap;
+ }
+ }
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ if (state->clip->test(xDest + x, yDest + y)) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ (this->*pipe.run)(&pipe);
+ updateModX(xDest + x);
+ updateModY(yDest + y);
+ } else {
+ pipeIncX(&pipe);
+ }
+ }
+ }
+ }
+ }
}
SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
@@ -2782,39 +4335,72 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
}
if (src->alpha) {
- pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha,
- gTrue, nonIsolated);
- for (y = 0; y < h; ++y) {
- pipeSetXY(&pipe, xDest, yDest + y);
- ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc;
- for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- alpha = *ap++;
- if (noClip || state->clip->test(xDest + x, yDest + y)) {
+ pipeInit(&pipe, xDest, yDest, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, nonIsolated);
+ if (noClip) {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc;
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ alpha = *ap++;
// this uses shape instead of alpha, which isn't technically
// correct, but works out the same
- pipe.shape = (SplashCoord)(alpha / 255.0);
- pipeRun(&pipe);
- updateModX(xDest + x);
- updateModY(yDest + y);
- } else {
- pipeIncX(&pipe);
+ pipe.shape = alpha;
+ (this->*pipe.run)(&pipe);
+ }
+ }
+ updateModX(xDest);
+ updateModX(xDest + w - 1);
+ updateModY(yDest);
+ updateModY(yDest + h - 1);
+ } else {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc;
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ alpha = *ap++;
+ if (state->clip->test(xDest + x, yDest + y)) {
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ pipe.shape = alpha;
+ (this->*pipe.run)(&pipe);
+ updateModX(xDest + x);
+ updateModY(yDest + y);
+ } else {
+ pipeIncX(&pipe);
+ }
}
}
}
} else {
- pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha,
- gFalse, nonIsolated);
- for (y = 0; y < h; ++y) {
- pipeSetXY(&pipe, xDest, yDest + y);
- for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- if (noClip || state->clip->test(xDest + x, yDest + y)) {
- pipeRun(&pipe);
- updateModX(xDest + x);
- updateModY(yDest + y);
- } else {
- pipeIncX(&pipe);
+ pipeInit(&pipe, xDest, yDest, NULL, pixel,
+ (Guchar)splashRound(state->fillAlpha * 255), gFalse, nonIsolated);
+ if (noClip) {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ (this->*pipe.run)(&pipe);
+ }
+ }
+ updateModX(xDest);
+ updateModX(xDest + w - 1);
+ updateModY(yDest);
+ updateModY(yDest + h - 1);
+ } else {
+ for (y = 0; y < h; ++y) {
+ pipeSetXY(&pipe, xDest, yDest + y);
+ for (x = 0; x < w; ++x) {
+ src->getPixel(xSrc + x, ySrc + y, pixel);
+ if (state->clip->test(xDest + x, yDest + y)) {
+ (this->*pipe.run)(&pipe);
+ updateModX(xDest + x);
+ updateModY(yDest + y);
+ } else {
+ pipeIncX(&pipe);
+ }
}
}
}
@@ -2826,7 +4412,10 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
void Splash::compositeBackground(SplashColorPtr color) {
SplashColorPtr p;
Guchar *q;
- Guchar alpha, alpha1, c, color0, color1, color2, color3;
+ Guchar alpha, alpha1, c, color0, color1, color2;
+#if SPLASH_CMYK
+ Guchar color3;
+#endif
int x, y, mask;
switch (bitmap->mode) {
@@ -2911,10 +4500,8 @@ void Splash::compositeBackground(SplashColorPtr color) {
SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
int xDest, int yDest, int w, int h) {
- SplashColor pixel;
- SplashColorPtr p;
- Guchar *q;
- int x, y, mask;
+ SplashColorPtr p, q;
+ int x, y, mask, srcMask;
if (src->mode != bitmap->mode) {
return splashErrModeMismatch;
@@ -2925,9 +4512,10 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
for (y = 0; y < h; ++y) {
p = &bitmap->data[(yDest + y) * bitmap->rowSize + (xDest >> 3)];
mask = 0x80 >> (xDest & 7);
+ q = &src->data[(ySrc + y) * src->rowSize + (xSrc >> 3)];
+ srcMask = 0x80 >> (xSrc & 7);
for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- if (pixel[0]) {
+ if (*q & srcMask) {
*p |= mask;
} else {
*p &= ~mask;
@@ -2936,15 +4524,19 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
mask = 0x80;
++p;
}
+ if (!(srcMask >>= 1)) {
+ srcMask = 0x80;
+ ++q;
+ }
}
}
break;
case splashModeMono8:
for (y = 0; y < h; ++y) {
p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + xSrc];
for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- *p++ = pixel[0];
+ *p++ = *q++;
}
}
break;
@@ -2952,11 +4544,11 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
case splashModeBGR8:
for (y = 0; y < h; ++y) {
p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + 3 * xSrc];
for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- *p++ = pixel[0];
- *p++ = pixel[1];
- *p++ = pixel[2];
+ *p++ = *q++;
+ *p++ = *q++;
+ *p++ = *q++;
}
}
break;
@@ -2964,12 +4556,12 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
case splashModeCMYK8:
for (y = 0; y < h; ++y) {
p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest];
+ q = &src->data[(ySrc + y) * src->rowSize + 4 * xSrc];
for (x = 0; x < w; ++x) {
- src->getPixel(xSrc + x, ySrc + y, pixel);
- *p++ = pixel[0];
- *p++ = pixel[1];
- *p++ = pixel[2];
- *p++ = pixel[3];
+ *p++ = *q++;
+ *p++ = *q++;
+ *p++ = *q++;
+ *p++ = *q++;
}
}
break;
@@ -2988,166 +4580,246 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
return splashOk;
}
-SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
- SplashPath *pathIn, *pathOut;
- SplashCoord w, d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
+SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
+ GBool flatten) {
+ SplashPath *pathIn, *dashPath, *pathOut;
+ SplashCoord d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
SplashCoord crossprod, dotprod, miter, m;
GBool first, last, closed;
- int subpathStart, next, i;
+ int subpathStart0, subpathStart1, seg, i0, i1, j0, j1, k0, k1;
int left0, left1, left2, right0, right1, right2, join0, join1, join2;
int leftFirst, rightFirst, firstPt;
+ pathOut = new SplashPath();
+
+ if (path->length == 0) {
+ return pathOut;
+ }
+
if (flatten) {
pathIn = flattenPath(path, state->matrix, state->flatness);
if (state->lineDashLength > 0) {
- pathOut = makeDashedPath(pathIn);
+ dashPath = makeDashedPath(pathIn);
delete pathIn;
- pathIn = pathOut;
+ pathIn = dashPath;
+ if (pathIn->length == 0) {
+ delete pathIn;
+ return pathOut;
+ }
}
} else {
pathIn = path;
}
- subpathStart = 0; // make gcc happy
+ subpathStart0 = subpathStart1 = 0; // make gcc happy
+ seg = 0; // make gcc happy
closed = gFalse; // make gcc happy
left0 = left1 = right0 = right1 = join0 = join1 = 0; // make gcc happy
leftFirst = rightFirst = firstPt = 0; // make gcc happy
- pathOut = new SplashPath();
- w = state->lineWidth;
-
- for (i = 0; i < pathIn->length - 1; ++i) {
- if (pathIn->flags[i] & splashPathLast) {
+ i0 = 0;
+ for (i1 = i0;
+ !(pathIn->flags[i1] & splashPathLast) &&
+ i1 + 1 < pathIn->length &&
+ pathIn->pts[i1+1].x == pathIn->pts[i1].x &&
+ pathIn->pts[i1+1].y == pathIn->pts[i1].y;
+ ++i1) ;
+
+ while (i1 < pathIn->length) {
+ if ((first = pathIn->flags[i0] & splashPathFirst)) {
+ subpathStart0 = i0;
+ subpathStart1 = i1;
+ seg = 0;
+ closed = pathIn->flags[i0] & splashPathClosed;
+ }
+ j0 = i1 + 1;
+ if (j0 < pathIn->length) {
+ for (j1 = j0;
+ !(pathIn->flags[j1] & splashPathLast) &&
+ j1 + 1 < pathIn->length &&
+ pathIn->pts[j1+1].x == pathIn->pts[j1].x &&
+ pathIn->pts[j1+1].y == pathIn->pts[j1].y;
+ ++j1) ;
+ } else {
+ j1 = j0;
+ }
+ if (pathIn->flags[i1] & splashPathLast) {
+ if (first && state->lineCap == splashLineCapRound) {
+ // special case: zero-length subpath with round line caps -->
+ // draw a circle
+ pathOut->moveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->curveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y + bezierCircle2 * w,
+ pathIn->pts[i0].x + bezierCircle2 * w,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[i0].x - bezierCircle2 * w,
+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y + bezierCircle2 * w,
+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->curveTo(pathIn->pts[i0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y - bezierCircle2 * w,
+ pathIn->pts[i0].x - bezierCircle2 * w,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[i0].x + bezierCircle2 * w,
+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y - bezierCircle2 * w,
+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[i0].y);
+ pathOut->close();
+ }
+ i0 = j0;
+ i1 = j1;
continue;
}
- if ((first = pathIn->flags[i] & splashPathFirst)) {
- subpathStart = i;
- closed = pathIn->flags[i] & splashPathClosed;
- }
- last = pathIn->flags[i+1] & splashPathLast;
-
- // compute the deltas for segment (i, i+1)
- d = splashDist(pathIn->pts[i].x, pathIn->pts[i].y,
- pathIn->pts[i+1].x, pathIn->pts[i+1].y);
- if (d == 0) {
- // we need to draw end caps on zero-length lines
- //~ not clear what the behavior should be for splashLineCapButt
- //~ with d==0
- dx = 0;
- dy = 1;
+ last = pathIn->flags[j1] & splashPathLast;
+ if (last) {
+ k0 = subpathStart1 + 1;
} else {
- d = (SplashCoord)1 / d;
- dx = d * (pathIn->pts[i+1].x - pathIn->pts[i].x);
- dy = d * (pathIn->pts[i+1].y - pathIn->pts[i].y);
+ k0 = j1 + 1;
}
+ for (k1 = k0;
+ !(pathIn->flags[k1] & splashPathLast) &&
+ k1 + 1 < pathIn->length &&
+ pathIn->pts[k1+1].x == pathIn->pts[k1].x &&
+ pathIn->pts[k1+1].y == pathIn->pts[k1].y;
+ ++k1) ;
+
+ // compute the deltas for segment (i1, j0)
+#if USE_FIXEDPOINT
+ // the 1/d value can be small, which introduces significant
+ // inaccuracies in fixed point mode
+ d = splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
+ pathIn->pts[j0].x, pathIn->pts[j0].y);
+ dx = (pathIn->pts[j0].x - pathIn->pts[i1].x) / d;
+ dy = (pathIn->pts[j0].y - pathIn->pts[i1].y) / d;
+#else
+ d = (SplashCoord)1 / splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
+ pathIn->pts[j0].x, pathIn->pts[j0].y);
+ dx = d * (pathIn->pts[j0].x - pathIn->pts[i1].x);
+ dy = d * (pathIn->pts[j0].y - pathIn->pts[i1].y);
+#endif
wdx = (SplashCoord)0.5 * w * dx;
wdy = (SplashCoord)0.5 * w * dy;
- // compute the deltas for segment (i+1, next)
- next = last ? subpathStart + 1 : i + 2;
- d = splashDist(pathIn->pts[i+1].x, pathIn->pts[i+1].y,
- pathIn->pts[next].x, pathIn->pts[next].y);
- if (d == 0) {
- // we need to draw end caps on zero-length lines
- //~ not clear what the behavior should be for splashLineCapButt
- //~ with d==0
- dxNext = 0;
- dyNext = 1;
- } else {
- d = (SplashCoord)1 / d;
- dxNext = d * (pathIn->pts[next].x - pathIn->pts[i+1].x);
- dyNext = d * (pathIn->pts[next].y - pathIn->pts[i+1].y);
- }
- wdxNext = (SplashCoord)0.5 * w * dxNext;
- wdyNext = (SplashCoord)0.5 * w * dyNext;
-
// draw the start cap
- pathOut->moveTo(pathIn->pts[i].x - wdy, pathIn->pts[i].y + wdx);
- if (i == subpathStart) {
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
+ if (i0 == subpathStart0) {
firstPt = pathOut->length - 1;
}
if (first && !closed) {
switch (state->lineCap) {
case splashLineCapButt:
- pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx);
+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
break;
case splashLineCapRound:
- pathOut->curveTo(pathIn->pts[i].x - wdy - bezierCircle * wdx,
- pathIn->pts[i].y + wdx - bezierCircle * wdy,
- pathIn->pts[i].x - wdx - bezierCircle * wdy,
- pathIn->pts[i].y - wdy + bezierCircle * wdx,
- pathIn->pts[i].x - wdx,
- pathIn->pts[i].y - wdy);
- pathOut->curveTo(pathIn->pts[i].x - wdx + bezierCircle * wdy,
- pathIn->pts[i].y - wdy - bezierCircle * wdx,
- pathIn->pts[i].x + wdy - bezierCircle * wdx,
- pathIn->pts[i].y - wdx - bezierCircle * wdy,
- pathIn->pts[i].x + wdy,
- pathIn->pts[i].y - wdx);
+ pathOut->curveTo(pathIn->pts[i0].x - wdy - bezierCircle * wdx,
+ pathIn->pts[i0].y + wdx - bezierCircle * wdy,
+ pathIn->pts[i0].x - wdx - bezierCircle * wdy,
+ pathIn->pts[i0].y - wdy + bezierCircle * wdx,
+ pathIn->pts[i0].x - wdx,
+ pathIn->pts[i0].y - wdy);
+ pathOut->curveTo(pathIn->pts[i0].x - wdx + bezierCircle * wdy,
+ pathIn->pts[i0].y - wdy - bezierCircle * wdx,
+ pathIn->pts[i0].x + wdy - bezierCircle * wdx,
+ pathIn->pts[i0].y - wdx - bezierCircle * wdy,
+ pathIn->pts[i0].x + wdy,
+ pathIn->pts[i0].y - wdx);
break;
case splashLineCapProjecting:
- pathOut->lineTo(pathIn->pts[i].x - wdx - wdy,
- pathIn->pts[i].y + wdx - wdy);
- pathOut->lineTo(pathIn->pts[i].x - wdx + wdy,
- pathIn->pts[i].y - wdx - wdy);
- pathOut->lineTo(pathIn->pts[i].x + wdy,
- pathIn->pts[i].y - wdx);
+ pathOut->lineTo(pathIn->pts[i0].x - wdx - wdy,
+ pathIn->pts[i0].y + wdx - wdy);
+ pathOut->lineTo(pathIn->pts[i0].x - wdx + wdy,
+ pathIn->pts[i0].y - wdx - wdy);
+ pathOut->lineTo(pathIn->pts[i0].x + wdy,
+ pathIn->pts[i0].y - wdx);
break;
}
} else {
- pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx);
+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
}
// draw the left side of the segment rectangle
left2 = pathOut->length - 1;
- pathOut->lineTo(pathIn->pts[i+1].x + wdy, pathIn->pts[i+1].y - wdx);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
// draw the end cap
if (last && !closed) {
switch (state->lineCap) {
case splashLineCapButt:
- pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
break;
case splashLineCapRound:
- pathOut->curveTo(pathIn->pts[i+1].x + wdy + bezierCircle * wdx,
- pathIn->pts[i+1].y - wdx + bezierCircle * wdy,
- pathIn->pts[i+1].x + wdx + bezierCircle * wdy,
- pathIn->pts[i+1].y + wdy - bezierCircle * wdx,
- pathIn->pts[i+1].x + wdx,
- pathIn->pts[i+1].y + wdy);
- pathOut->curveTo(pathIn->pts[i+1].x + wdx - bezierCircle * wdy,
- pathIn->pts[i+1].y + wdy + bezierCircle * wdx,
- pathIn->pts[i+1].x - wdy + bezierCircle * wdx,
- pathIn->pts[i+1].y + wdx + bezierCircle * wdy,
- pathIn->pts[i+1].x - wdy,
- pathIn->pts[i+1].y + wdx);
+ pathOut->curveTo(pathIn->pts[j0].x + wdy + bezierCircle * wdx,
+ pathIn->pts[j0].y - wdx + bezierCircle * wdy,
+ pathIn->pts[j0].x + wdx + bezierCircle * wdy,
+ pathIn->pts[j0].y + wdy - bezierCircle * wdx,
+ pathIn->pts[j0].x + wdx,
+ pathIn->pts[j0].y + wdy);
+ pathOut->curveTo(pathIn->pts[j0].x + wdx - bezierCircle * wdy,
+ pathIn->pts[j0].y + wdy + bezierCircle * wdx,
+ pathIn->pts[j0].x - wdy + bezierCircle * wdx,
+ pathIn->pts[j0].y + wdx + bezierCircle * wdy,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
break;
case splashLineCapProjecting:
- pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx,
- pathIn->pts[i+1].y - wdx + wdy);
- pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx,
- pathIn->pts[i+1].y + wdx + wdy);
- pathOut->lineTo(pathIn->pts[i+1].x - wdy,
- pathIn->pts[i+1].y + wdx);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx,
+ pathIn->pts[j0].y - wdx + wdy);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx,
+ pathIn->pts[j0].y + wdx + wdy);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
break;
}
} else {
- pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
}
// draw the right side of the segment rectangle
+ // (NB: if stroke adjustment is enabled, the closepath operation MUST
+ // add a segment because this segment is used for a hint)
right2 = pathOut->length - 1;
- pathOut->close();
+ pathOut->close(state->strokeAdjust);
// draw the join
join2 = pathOut->length;
if (!last || closed) {
+
+ // compute the deltas for segment (j1, k0)
+#if USE_FIXEDPOINT
+ // the 1/d value can be small, which introduces significant
+ // inaccuracies in fixed point mode
+ d = splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
+ pathIn->pts[k0].x, pathIn->pts[k0].y);
+ dxNext = (pathIn->pts[k0].x - pathIn->pts[j1].x) / d;
+ dyNext = (pathIn->pts[k0].y - pathIn->pts[j1].y) / d;
+#else
+ d = (SplashCoord)1 / splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
+ pathIn->pts[k0].x, pathIn->pts[k0].y);
+ dxNext = d * (pathIn->pts[k0].x - pathIn->pts[j1].x);
+ dyNext = d * (pathIn->pts[k0].y - pathIn->pts[j1].y);
+#endif
+ wdxNext = (SplashCoord)0.5 * w * dxNext;
+ wdyNext = (SplashCoord)0.5 * w * dyNext;
+
+ // compute the join parameters
crossprod = dx * dyNext - dy * dxNext;
dotprod = -(dx * dxNext + dy * dyNext);
- if (dotprod > 0.99999) {
+ if (dotprod > 0.9999) {
// avoid a divide-by-zero -- set miter to something arbitrary
// such that sqrt(miter) will exceed miterLimit (and m is never
// used in that situation)
+ // (note: the comparison value (0.9999) has to be less than
+ // 1-epsilon, where epsilon is the smallest value
+ // representable in the fixed point format)
miter = (state->miterLimit + 1) * (state->miterLimit + 1);
m = 0;
} else {
@@ -3161,67 +4833,68 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
// round join
if (state->lineJoin == splashLineJoinRound) {
- pathOut->moveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y);
- pathOut->curveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y + bezierCircle2 * w,
- pathIn->pts[i+1].x + bezierCircle2 * w,
- pathIn->pts[i+1].y + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].x,
- pathIn->pts[i+1].y + (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[i+1].x - bezierCircle2 * w,
- pathIn->pts[i+1].y + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y + bezierCircle2 * w,
- pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y);
- pathOut->curveTo(pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y - bezierCircle2 * w,
- pathIn->pts[i+1].x - bezierCircle2 * w,
- pathIn->pts[i+1].y - (SplashCoord)0.5 * w,
- pathIn->pts[i+1].x,
- pathIn->pts[i+1].y - (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[i+1].x + bezierCircle2 * w,
- pathIn->pts[i+1].y - (SplashCoord)0.5 * w,
- pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y - bezierCircle2 * w,
- pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
- pathIn->pts[i+1].y);
+ pathOut->moveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y);
+ pathOut->curveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y + bezierCircle2 * w,
+ pathIn->pts[j0].x + bezierCircle2 * w,
+ pathIn->pts[j0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].x,
+ pathIn->pts[j0].y + (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[j0].x - bezierCircle2 * w,
+ pathIn->pts[j0].y + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y + bezierCircle2 * w,
+ pathIn->pts[j0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y);
+ pathOut->curveTo(pathIn->pts[j0].x - (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y - bezierCircle2 * w,
+ pathIn->pts[j0].x - bezierCircle2 * w,
+ pathIn->pts[j0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[j0].x,
+ pathIn->pts[j0].y - (SplashCoord)0.5 * w);
+ pathOut->curveTo(pathIn->pts[j0].x + bezierCircle2 * w,
+ pathIn->pts[j0].y - (SplashCoord)0.5 * w,
+ pathIn->pts[j0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y - bezierCircle2 * w,
+ pathIn->pts[j0].x + (SplashCoord)0.5 * w,
+ pathIn->pts[j0].y);
} else {
- pathOut->moveTo(pathIn->pts[i+1].x, pathIn->pts[i+1].y);
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
// angle < 180
if (crossprod < 0) {
- pathOut->lineTo(pathIn->pts[i+1].x - wdyNext,
- pathIn->pts[i+1].y + wdxNext);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
// miter join inside limit
if (state->lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
- pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx * m,
- pathIn->pts[i+1].y + wdx + wdy * m);
- pathOut->lineTo(pathIn->pts[i+1].x - wdy,
- pathIn->pts[i+1].y + wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx * m,
+ pathIn->pts[j0].y + wdx + wdy * m);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
// bevel join or miter join outside limit
} else {
- pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
}
// angle >= 180
} else {
- pathOut->lineTo(pathIn->pts[i+1].x + wdy,
- pathIn->pts[i+1].y - wdx);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
// miter join inside limit
if (state->lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
- pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx * m,
- pathIn->pts[i+1].y - wdx + wdy * m);
- pathOut->lineTo(pathIn->pts[i+1].x + wdyNext,
- pathIn->pts[i+1].y - wdxNext);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx * m,
+ pathIn->pts[j0].y - wdx + wdy * m);
+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
// bevel join or miter join outside limit
} else {
- pathOut->lineTo(pathIn->pts[i+1].x + wdyNext,
- pathIn->pts[i+1].y - wdxNext);
+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
}
}
}
@@ -3231,8 +4904,28 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
// add stroke adjustment hints
if (state->strokeAdjust) {
- if (i >= subpathStart + 1) {
- if (i >= subpathStart + 2) {
+ if (seg == 0 && !closed) {
+ if (state->lineCap == splashLineCapButt) {
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ firstPt, firstPt + 1);
+ if (last) {
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ left2 + 1, left2 + 2);
+ }
+ } else if (state->lineCap == splashLineCapProjecting) {
+ if (last) {
+ pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
+ firstPt + 1, firstPt + 2);
+ pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
+ left2 + 2, left2 + 3);
+ } else {
+ pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 1,
+ firstPt + 1, firstPt + 2);
+ }
+ }
+ }
+ if (seg >= 1) {
+ if (seg >= 2) {
pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
pathOut->addStrokeAdjustHint(left1, right1, join0, left2);
} else {
@@ -3246,12 +4939,12 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
right1 = right2;
join0 = join1;
join1 = join2;
- if (i == subpathStart) {
+ if (seg == 0) {
leftFirst = left2;
rightFirst = right2;
}
if (last) {
- if (i >= subpathStart + 2) {
+ if (seg >= 2) {
pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
pathOut->addStrokeAdjustHint(left1, right1,
join0, pathOut->length - 1);
@@ -3268,8 +4961,21 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
join1, pathOut->length - 1);
}
+ if (!closed && seg > 0) {
+ if (state->lineCap == splashLineCapButt) {
+ pathOut->addStrokeAdjustHint(left1 - 1, left1 + 1,
+ left1 + 1, left1 + 2);
+ } else if (state->lineCap == splashLineCapProjecting) {
+ pathOut->addStrokeAdjustHint(left1 - 1, left1 + 2,
+ left1 + 2, left1 + 3);
+ }
+ }
}
}
+
+ i0 = j0;
+ i1 = j1;
+ ++seg;
}
if (pathIn != path) {
@@ -3296,13 +5002,9 @@ void Splash::dumpXPath(SplashXPath *path) {
int i;
for (i = 0; i < path->length; ++i) {
- printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s%s%s%s%s\n",
+ printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s\n",
i, (double)path->segs[i].x0, (double)path->segs[i].y0,
(double)path->segs[i].x1, (double)path->segs[i].y1,
- (path->segs[i].flags & splashXPathFirst) ? "F" : " ",
- (path->segs[i].flags & splashXPathLast) ? "L" : " ",
- (path->segs[i].flags & splashXPathEnd0) ? "0" : " ",
- (path->segs[i].flags & splashXPathEnd1) ? "1" : " ",
(path->segs[i].flags & splashXPathHoriz) ? "H" : " ",
(path->segs[i].flags & splashXPathVert) ? "V" : " ",
(path->segs[i].flags & splashXPathFlip) ? "P" : " ");
diff --git a/splash/Splash.h b/splash/Splash.h
index c624622..30761fb 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -43,11 +43,11 @@ typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine,
//------------------------------------------------------------------------
enum SplashPipeResultColorCtrl {
+ splashPipeResultColorNoAlphaBlendMono,
+ splashPipeResultColorNoAlphaBlendRGB,
#if SPLASH_CMYK
splashPipeResultColorNoAlphaBlendCMYK,
#endif
- splashPipeResultColorNoAlphaBlendRGB,
- splashPipeResultColorNoAlphaBlendMono,
splashPipeResultColorAlphaNoBlendMono,
splashPipeResultColorAlphaNoBlendRGB,
#if SPLASH_CMYK
@@ -93,6 +93,7 @@ public:
SplashCoord *getLineDash();
int getLineDashLength();
SplashCoord getLineDashPhase();
+ GBool getStrokeAdjust();
SplashClip *getClip();
SplashBitmap *getSoftMask();
GBool getInNonIsolatedGroup();
@@ -126,6 +127,8 @@ public:
void setSoftMask(SplashBitmap *softMask);
void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA,
int alpha0XA, int alpha0YA);
+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
+ void setOverprintMask(Guint overprintMask);
//----- state save/restore
@@ -208,14 +211,19 @@ public:
//----- misc
- // Construct a path for a stroke, given the path to be stroked, and
- // using the current line parameters. If <flatten> is true, this
- // function will first flatten the path and handle the linedash.
- SplashPath *makeStrokePath(SplashPath *path, GBool flatten = gTrue);
+ // Construct a path for a stroke, given the path to be stroked and
+ // the line width <w>. All other stroke parameters are taken from
+ // the current state. If <flatten> is true, this function will
+ // first flatten the path and handle the linedash.
+ SplashPath *makeStrokePath(SplashPath *path, SplashCoord w,
+ GBool flatten = gTrue);
// Return the associated bitmap.
SplashBitmap *getBitmap() { return bitmap; }
+ // Set the minimum line width.
+ void setMinLineWidth(SplashCoord w) { minLineWidth = w; }
+
// Get a bounding box which includes all modifications since the
// last call to clearModRegion.
void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax)
@@ -232,17 +240,30 @@ public:
void setDebugMode(GBool debugModeA) { debugMode = debugModeA; }
#if 1 //~tmp: turn off anti-aliasing temporarily
- GBool getVectorAntialias() { return vectorAntialias; }
- void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; }
+ void setInShading(GBool sh) { inShading = sh; }
#endif
private:
void pipeInit(SplashPipe *pipe, int x, int y,
SplashPattern *pattern, SplashColorPtr cSrc,
- SplashCoord aInput, GBool usesShape,
+ Guchar aInput, GBool usesShape,
GBool nonIsolatedGroup);
void pipeRun(SplashPipe *pipe);
+ void pipeRunSimpleMono1(SplashPipe *pipe);
+ void pipeRunSimpleMono8(SplashPipe *pipe);
+ void pipeRunSimpleRGB8(SplashPipe *pipe);
+ void pipeRunSimpleBGR8(SplashPipe *pipe);
+#if SPLASH_CMYK
+ void pipeRunSimpleCMYK8(SplashPipe *pipe);
+#endif
+ void pipeRunAAMono1(SplashPipe *pipe);
+ void pipeRunAAMono8(SplashPipe *pipe);
+ void pipeRunAARGB8(SplashPipe *pipe);
+ void pipeRunAABGR8(SplashPipe *pipe);
+#if SPLASH_CMYK
+ void pipeRunAACMYK8(SplashPipe *pipe);
+#endif
void pipeSetXY(SplashPipe *pipe, int x, int y);
void pipeIncX(SplashPipe *pipe);
void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip);
@@ -255,7 +276,7 @@ private:
void updateModX(int x);
void updateModY(int y);
void strokeNarrow(SplashPath *path);
- void strokeWide(SplashPath *path);
+ void strokeWide(SplashPath *path, SplashCoord w);
SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix,
SplashCoord flatness);
void flattenCurve(SplashCoord x0, SplashCoord y0,
@@ -267,7 +288,68 @@ private:
SplashPath *makeDashedPath(SplashPath *xPath);
SplashError fillWithPattern(SplashPath *path, GBool eo,
SplashPattern *pattern, SplashCoord alpha);
+ GBool pathAllOutside(SplashPath *path);
SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph);
+ void arbitraryTransformMask(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ SplashCoord *mat, GBool glyphMode);
+ SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight);
+ void scaleMaskYdXd(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleMaskYdXu(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleMaskYuXd(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void blitMask(SplashBitmap *src, int xDest, int yDest,
+ SplashClipResult clipRes);
+ void arbitraryTransformImage(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha,
+ int srcWidth, int srcHeight,
+ SplashCoord *mat);
+ SplashBitmap *scaleImage(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight);
+ void scaleImageYdXd(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleImageYdXu(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleImageYuXd(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void scaleImageYuXu(SplashImageSource src, void *srcData,
+ SplashColorMode srcMode, int nComps,
+ GBool srcAlpha, int srcWidth, int srcHeight,
+ int scaledWidth, int scaledHeight,
+ SplashBitmap *dest);
+ void vertFlipImage(SplashBitmap *img, int width, int height,
+ int nComps);
+ void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest,
+ SplashClipResult clipRes);
+ void blitImageClipped(SplashBitmap *src, GBool srcAlpha,
+ int xSrc, int ySrc, int xDest, int yDest,
+ int w, int h);
void dumpPath(SplashPath *path);
void dumpXPath(SplashXPath *path);
@@ -283,10 +365,12 @@ private:
SplashBitmap *alpha0Bitmap; // for non-isolated groups, this is the
// bitmap containing the alpha0 values
int alpha0X, alpha0Y; // offset within alpha0Bitmap
- SplashCoord aaGamma[splashAASize * splashAASize + 1];
+ Guchar aaGamma[splashAASize * splashAASize + 1];
+ SplashCoord minLineWidth;
int modXMin, modYMin, modXMax, modYMax;
SplashClipResult opClipRes;
GBool vectorAntialias;
+ GBool inShading;
GBool debugMode;
};
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index 0cb1a75..9fc7b04 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -11,6 +11,7 @@
#endif
#include <stdio.h>
+#include <limits.h>
#include "gmem.h"
#include "SplashErrorCodes.h"
#include "SplashBitmap.h"
@@ -27,53 +28,79 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad,
mode = modeA;
switch (mode) {
case splashModeMono1:
- rowSize = (width + 7) >> 3;
+ if (width > 0) {
+ rowSize = (width + 7) >> 3;
+ } else {
+ rowSize = -1;
+ }
break;
case splashModeMono8:
- rowSize = width;
+ if (width > 0) {
+ rowSize = width;
+ } else {
+ rowSize = -1;
+ }
break;
case splashModeRGB8:
case splashModeBGR8:
- rowSize = width * 3;
+ if (width > 0 && width <= INT_MAX / 3) {
+ rowSize = width * 3;
+ } else {
+ rowSize = -1;
+ }
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- rowSize = width * 4;
+ if (width > 0 && width <= INT_MAX / 4) {
+ rowSize = width * 4;
+ } else {
+ rowSize = -1;
+ }
break;
#endif
}
- rowSize += rowPad - 1;
- rowSize -= rowSize % rowPad;
- data = (SplashColorPtr)gmalloc(rowSize * height);
+ if (rowSize > 0) {
+ rowSize += rowPad - 1;
+ rowSize -= rowSize % rowPad;
+ }
+ data = (SplashColorPtr)gmallocn(height, rowSize);
if (!topDown) {
data += (height - 1) * rowSize;
rowSize = -rowSize;
}
if (alphaA) {
- alpha = (Guchar *)gmalloc(width * height);
+ alpha = (Guchar *)gmallocn(width, height);
} else {
alpha = NULL;
}
}
-
SplashBitmap::~SplashBitmap() {
- if (rowSize < 0) {
- gfree(data + (height - 1) * rowSize);
- } else {
- gfree(data);
+ if (data) {
+ if (rowSize < 0) {
+ gfree(data + (height - 1) * rowSize);
+ } else {
+ gfree(data);
+ }
}
gfree(alpha);
}
SplashError SplashBitmap::writePNMFile(char *fileName) {
FILE *f;
- SplashColorPtr row, p;
- int x, y;
+ SplashError err;
if (!(f = fopen(fileName, "wb"))) {
return splashErrOpenFile;
}
+ err = writePNMFile(f);
+ fclose(f);
+ return err;
+}
+
+SplashError SplashBitmap::writePNMFile(FILE *f) {
+ SplashColorPtr row, p;
+ int x, y;
switch (mode) {
@@ -94,11 +121,7 @@ SplashError SplashBitmap::writePNMFile(char *fileName) {
fprintf(f, "P5\n%d %d\n255\n", width, height);
row = data;
for (y = 0; y < height; ++y) {
- p = row;
- for (x = 0; x < width; ++x) {
- fputc(*p, f);
- ++p;
- }
+ fwrite(row, 1, width, f);
row += rowSize;
}
break;
@@ -107,13 +130,7 @@ SplashError SplashBitmap::writePNMFile(char *fileName) {
fprintf(f, "P6\n%d %d\n255\n", width, height);
row = data;
for (y = 0; y < height; ++y) {
- p = row;
- for (x = 0; x < width; ++x) {
- fputc(splashRGB8R(p), f);
- fputc(splashRGB8G(p), f);
- fputc(splashRGB8B(p), f);
- p += 3;
- }
+ fwrite(row, 1, 3 * width, f);
row += rowSize;
}
break;
@@ -138,12 +155,28 @@ SplashError SplashBitmap::writePNMFile(char *fileName) {
// PNM doesn't support CMYK
break;
#endif
+
}
+ return splashOk;
+}
+
+SplashError SplashBitmap::writeAlphaPGMFile(char *fileName) {
+ FILE *f;
+
+ if (!alpha) {
+ return splashErrModeMismatch;
+ }
+ if (!(f = fopen(fileName, "wb"))) {
+ return splashErrOpenFile;
+ }
+ fprintf(f, "P5\n%d %d\n255\n", width, height);
+ fwrite(alpha, 1, width * height, f);
fclose(f);
return splashOk;
}
+
void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) {
SplashColorPtr p;
@@ -186,3 +219,11 @@ void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) {
Guchar SplashBitmap::getAlpha(int x, int y) {
return alpha[y * width + x];
}
+
+SplashColorPtr SplashBitmap::takeData() {
+ SplashColorPtr data2;
+
+ data2 = data;
+ data = NULL;
+ return data2;
+}
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index 69ab058..78f37d6 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -13,6 +13,7 @@
#pragma interface
#endif
+#include <stdio.h>
#include "SplashTypes.h"
//------------------------------------------------------------------------
@@ -41,10 +42,17 @@ public:
Guchar *getAlphaPtr() { return alpha; }
SplashError writePNMFile(char *fileName);
+ SplashError writePNMFile(FILE *f);
+ SplashError writeAlphaPGMFile(char *fileName);
void getPixel(int x, int y, SplashColorPtr pixel);
Guchar getAlpha(int x, int y);
+ // Caller takes ownership of the bitmap data. The SplashBitmap
+ // object is no longer valid -- the next call should be to the
+ // destructor.
+ SplashColorPtr takeData();
+
private:
int width, height; // size of bitmap
diff --git a/splash/SplashClip.cc b/splash/SplashClip.cc
index ef8acba..da85771 100644
--- a/splash/SplashClip.cc
+++ b/splash/SplashClip.cc
@@ -50,8 +50,8 @@ SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
}
xMinI = splashFloor(xMin);
yMinI = splashFloor(yMin);
- xMaxI = splashFloor(xMax);
- yMaxI = splashFloor(yMax);
+ xMaxI = splashCeil(xMax) - 1;
+ yMaxI = splashCeil(yMax) - 1;
paths = NULL;
flags = NULL;
scanners = NULL;
@@ -59,6 +59,7 @@ SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
}
SplashClip::SplashClip(SplashClip *clip) {
+ int yMinAA, yMaxAA;
int i;
antialias = clip->antialias;
@@ -79,7 +80,15 @@ SplashClip::SplashClip(SplashClip *clip) {
for (i = 0; i < length; ++i) {
paths[i] = clip->paths[i]->copy();
flags[i] = clip->flags[i];
- scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
+ if (antialias) {
+ yMinAA = yMinI * splashAASize;
+ yMaxAA = (yMaxI + 1) * splashAASize - 1;
+ } else {
+ yMinAA = yMinI;
+ yMaxAA = yMaxI;
+ }
+ scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO,
+ yMinAA, yMaxAA);
}
}
@@ -142,8 +151,8 @@ void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
}
xMinI = splashFloor(xMin);
yMinI = splashFloor(yMin);
- xMaxI = splashFloor(xMax);
- yMaxI = splashFloor(yMax);
+ xMaxI = splashCeil(xMax) - 1;
+ yMaxI = splashCeil(yMax) - 1;
}
SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
@@ -155,7 +164,7 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
}
if (x1 < xMax) {
xMax = x1;
- xMaxI = splashFloor(xMax);
+ xMaxI = splashCeil(xMax) - 1;
}
} else {
if (x1 > xMin) {
@@ -164,7 +173,7 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
}
if (x0 < xMax) {
xMax = x0;
- xMaxI = splashFloor(xMax);
+ xMaxI = splashCeil(xMax) - 1;
}
}
if (y0 < y1) {
@@ -174,7 +183,7 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
}
if (y1 < yMax) {
yMax = y1;
- yMaxI = splashFloor(yMax);
+ yMaxI = splashCeil(yMax) - 1;
}
} else {
if (y1 > yMin) {
@@ -183,7 +192,7 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
}
if (y0 < yMax) {
yMax = y0;
- yMaxI = splashFloor(yMax);
+ yMaxI = splashCeil(yMax) - 1;
}
}
return splashOk;
@@ -192,6 +201,7 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
SplashCoord flatness, GBool eo) {
SplashXPath *xPath;
+ int yMinAA, yMaxAA;
xPath = new SplashXPath(path, matrix, flatness, gTrue);
@@ -199,8 +209,8 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
if (xPath->length == 0) {
xMax = xMin - 1;
yMax = yMin - 1;
- xMaxI = splashFloor(xMax);
- yMaxI = splashFloor(yMax);
+ xMaxI = splashCeil(xMax) - 1;
+ yMaxI = splashCeil(yMax) - 1;
delete xPath;
// check for a rectangle
@@ -241,7 +251,14 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
xPath->sort();
paths[length] = xPath;
flags[length] = eo ? splashClipEO : 0;
- scanners[length] = new SplashXPathScanner(xPath, eo);
+ if (antialias) {
+ yMinAA = yMinI * splashAASize;
+ yMaxAA = (yMaxI + 1) * splashAASize - 1;
+ } else {
+ yMinAA = yMinI;
+ yMaxAA = yMaxI;
+ }
+ scanners[length] = new SplashXPathScanner(xPath, eo, yMinAA, yMaxAA);
++length;
}
@@ -280,10 +297,10 @@ SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
// x = [rectXMin, rectXMax + 1) (note: rect coords are ints)
// y = [rectYMin, rectYMax + 1)
// against the clipping region:
- // x = [xMin, xMax] (note: clipping coords are fp)
- // y = [yMin, yMax]
- if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax ||
- (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) {
+ // x = [xMin, xMax) (note: clipping coords are fp)
+ // y = [yMin, yMax)
+ if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin >= xMax ||
+ (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin >= yMax) {
return splashClipAllOutside;
}
if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax &&
@@ -301,10 +318,10 @@ SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
// x = [spanXMin, spanXMax + 1) (note: span coords are ints)
// y = [spanY, spanY + 1)
// against the clipping region:
- // x = [xMin, xMax] (note: clipping coords are fp)
- // y = [yMin, yMax]
- if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax ||
- (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) {
+ // x = [xMin, xMax) (note: clipping coords are fp)
+ // y = [yMin, yMax)
+ if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin >= xMax ||
+ (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY >= yMax) {
return splashClipAllOutside;
}
if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax &&
diff --git a/splash/SplashClip.h b/splash/SplashClip.h
index 8ae2154..6f580f8 100644
--- a/splash/SplashClip.h
+++ b/splash/SplashClip.h
@@ -81,6 +81,12 @@ public:
// will update <x0> and <x1>.
void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+ // Get the rectangle part of the clip region.
+ SplashCoord getXMin() { return xMin; }
+ SplashCoord getXMax() { return xMax; }
+ SplashCoord getYMin() { return yMin; }
+ SplashCoord getYMax() { return yMax; }
+
// Get the rectangle part of the clip region, in integer coordinates.
int getXMinI() { return xMinI; }
int getXMaxI() { return xMaxI; }
diff --git a/splash/SplashFTFont.cc b/splash/SplashFTFont.cc
index 21b76c6..218f13e 100644
--- a/splash/SplashFTFont.cc
+++ b/splash/SplashFTFont.cc
@@ -20,6 +20,7 @@
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashPath.h"
+#include "SplashFontEngine.h"
#include "SplashFTFontEngine.h"
#include "SplashFTFontFile.h"
#include "SplashFTFont.h"
@@ -42,24 +43,84 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa)
{
FT_Face face;
- SplashCoord size, div;
+ int size, div;
int x, y;
+#if USE_FIXEDPOINT
+ SplashCoord scale;
+#endif
face = fontFileA->face;
if (FT_New_Size(face, &sizeObj)) {
return;
}
face->size = sizeObj;
- size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
- if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
+ size = splashRound(splashDist(0, 0, mat[2], mat[3]));
+ if (size < 1) {
+ size = 1;
+ }
+ if (FT_Set_Pixel_Sizes(face, 0, size)) {
return;
}
// if the textMat values are too small, FreeType's fixed point
// arithmetic doesn't work so well
- textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / size;
+ textScale = splashDist(0, 0, textMat[2], textMat[3]) / size;
div = face->bbox.xMax > 20000 ? 65536 : 1;
+#if USE_FIXEDPOINT
+ scale = (SplashCoord)1 / (SplashCoord)face->units_per_EM;
+
+ // transform the four corners of the font bounding box -- the min
+ // and max values form the bounding box of the transformed font
+ x = (int)(mat[0] * (scale * (face->bbox.xMin / div)) +
+ mat[2] * (scale * (face->bbox.yMin / div)));
+ xMin = xMax = x;
+ y = (int)(mat[1] * (scale * (face->bbox.xMin / div)) +
+ mat[3] * (scale * (face->bbox.yMin / div)));
+ yMin = yMax = y;
+ x = (int)(mat[0] * (scale * (face->bbox.xMin / div)) +
+ mat[2] * (scale * (face->bbox.yMax / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMin / div)) +
+ mat[3] * (scale * (face->bbox.yMax / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)(mat[0] * (scale * (face->bbox.xMax / div)) +
+ mat[2] * (scale * (face->bbox.yMin / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMax / div)) +
+ mat[3] * (scale * (face->bbox.yMin / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ x = (int)(mat[0] * (scale * (face->bbox.xMax / div)) +
+ mat[2] * (scale * (face->bbox.yMax / div)));
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ y = (int)(mat[1] * (scale * (face->bbox.xMax / div)) +
+ mat[3] * (scale * (face->bbox.yMax / div)));
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+#else // USE_FIXEDPOINT
// transform the four corners of the font bounding box -- the min
// and max values form the bounding box of the transformed font
x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) /
@@ -110,11 +171,12 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
} else if (y > yMax) {
yMax = y;
}
+#endif // USE_FIXEDPOINT
// This is a kludge: some buggy PDF generators embed fonts with
// zero bounding boxes.
if (xMax == xMin) {
xMin = 0;
- xMax = (int)size;
+ xMax = size;
}
if (yMax == yMin) {
yMin = 0;
@@ -123,23 +185,23 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
// compute the transform matrix
#if USE_FIXEDPOINT
- matrix.xx = (FT_Fixed)((mat[0] / size).getRaw());
- matrix.yx = (FT_Fixed)((mat[1] / size).getRaw());
- matrix.xy = (FT_Fixed)((mat[2] / size).getRaw());
- matrix.yy = (FT_Fixed)((mat[3] / size).getRaw());
- textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)).getRaw());
- textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)).getRaw());
- textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)).getRaw());
- textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)).getRaw());
+ matrix.xx = (FT_Fixed)((mat[0] / size).get16Dot16());
+ matrix.yx = (FT_Fixed)((mat[1] / size).get16Dot16());
+ matrix.xy = (FT_Fixed)((mat[2] / size).get16Dot16());
+ matrix.yy = (FT_Fixed)((mat[3] / size).get16Dot16());
+ textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).get16Dot16());
+ textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).get16Dot16());
+ textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).get16Dot16());
+ textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).get16Dot16());
#else
matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
- textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)) * 65536);
- textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)) * 65536);
- textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)) * 65536);
- textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)) * 65536);
+ textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)) * 65536);
+ textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)) * 65536);
+ textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)) * 65536);
+ textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)) * 65536);
#endif
}
@@ -157,6 +219,7 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
FT_Vector offset;
FT_GlyphSlot slot;
FT_UInt gid;
+ FT_Int32 flags;
int rowSize;
Guchar *p, *q;
int i;
@@ -174,30 +237,39 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
} else {
gid = (FT_UInt)c;
}
- if (ff->trueType && gid == 0) {
+ if (ff->trueType && gid < 0) {
// skip the TrueType notdef glyph
return gFalse;
}
- // if we have the FT2 bytecode interpreter, autohinting won't be used
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- if (FT_Load_Glyph(ff->face, gid,
- aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) {
+ flags = 0;
+ if (aa) {
+ flags |= FT_LOAD_NO_BITMAP;
+ }
+ if (ff->engine->flags & splashFTNoHinting) {
+ flags |= FT_LOAD_NO_HINTING;
+ } else if (ff->trueType) {
+ // FT2's autohinting doesn't always work very well (especially with
+ // font subsets), so turn it off if anti-aliasing is enabled; if
+ // anti-aliasing is disabled, this seems to be a tossup - some fonts
+ // look better with hinting, some without, so leave hinting on
+ if (aa) {
+ flags |= FT_LOAD_NO_AUTOHINT;
+ }
+ } else if (ff->type1) {
+ // Type 1 fonts seem to look better with 'light' hinting mode
+ flags |= FT_LOAD_TARGET_LIGHT;
+ }
+ if (FT_Load_Glyph(ff->face, gid, flags)) {
return gFalse;
}
-#else
- // FT2's autohinting doesn't always work very well (especially with
- // font subsets), so turn it off if anti-aliasing is enabled; if
- // anti-aliasing is disabled, this seems to be a tossup - some fonts
- // look better with hinting, some without, so leave hinting on
- if (FT_Load_Glyph(ff->face, gid,
- aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
- : FT_LOAD_DEFAULT)) {
+ if (FT_Render_Glyph(slot, aa ? FT_RENDER_MODE_NORMAL
+ : FT_RENDER_MODE_MONO)) {
return gFalse;
}
-#endif
- if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
- : ft_render_mode_mono)) {
+ if (slot->bitmap.width == 0 || slot->bitmap.rows == 0) {
+ // this can happen if (a) the glyph is really tiny or (b) the
+ // metrics in the TrueType file are broken
return gFalse;
}
@@ -211,7 +283,7 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
} else {
rowSize = (bitmap->w + 7) >> 3;
}
- bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h);
+ bitmap->data = (Guchar *)gmallocn(bitmap->h, rowSize);
bitmap->freeData = gTrue;
for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
i < bitmap->h;
@@ -258,7 +330,7 @@ SplashPath *SplashFTFont::getGlyphPath(int c) {
} else {
gid = (FT_UInt)c;
}
- if (ff->trueType && gid == 0) {
+ if (ff->trueType && gid < 0) {
// skip the TrueType notdef glyph
return NULL;
}
diff --git a/splash/SplashFTFontEngine.cc b/splash/SplashFTFontEngine.cc
index 2270f7b..9a4533a 100644
--- a/splash/SplashFTFontEngine.cc
+++ b/splash/SplashFTFontEngine.cc
@@ -32,7 +32,7 @@ extern "C" int unlink(char *filename);
//------------------------------------------------------------------------
-static void fileWrite(void *stream, char *data, int len) {
+static void fileWrite(void *stream, const char *data, int len) {
fwrite(data, 1, len, (FILE *)stream);
}
@@ -40,10 +40,12 @@ static void fileWrite(void *stream, char *data, int len) {
// SplashFTFontEngine
//------------------------------------------------------------------------
-SplashFTFontEngine::SplashFTFontEngine(GBool aaA, FT_Library libA) {
+SplashFTFontEngine::SplashFTFontEngine(GBool aaA, Guint flagsA,
+ FT_Library libA) {
FT_Int major, minor, patch;
aa = aaA;
+ flags = flagsA;
lib = libA;
// as of FT 2.1.8, CID fonts are indexed by CID instead of GID
@@ -52,13 +54,13 @@ SplashFTFontEngine::SplashFTFontEngine(GBool aaA, FT_Library libA) {
(major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
}
-SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA) {
+SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA, Guint flagsA) {
FT_Library libA;
if (FT_Init_FreeType(&libA)) {
return NULL;
}
- return new SplashFTFontEngine(aaA, libA);
+ return new SplashFTFontEngine(aaA, flagsA, libA);
}
SplashFTFontEngine::~SplashFTFontEngine() {
@@ -68,21 +70,21 @@ SplashFTFontEngine::~SplashFTFontEngine() {
SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
@@ -90,7 +92,7 @@ SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile) {
FoFiType1C *ff;
- Gushort *cidToGIDMap;
+ int *cidToGIDMap;
int nCIDs;
SplashFontFile *ret;
@@ -115,26 +117,31 @@ SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
char *fileName,
- GBool deleteFile) {
+ GBool deleteFile,
+ int *codeToGID,
+ int codeToGIDLen) {
FoFiTrueType *ff;
GBool isCID;
- Gushort *cidToGIDMap;
+ int *cidToGIDMap;
int nCIDs;
SplashFontFile *ret;
cidToGIDMap = NULL;
nCIDs = 0;
isCID = gFalse;
- if (!useCIDs) {
- if ((ff = FoFiTrueType::load(fileName))) {
- if (ff->isOpenTypeCFF()) {
- cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ if (!codeToGID) {
+ if (!useCIDs) {
+ if ((ff = FoFiTrueType::load(fileName))) {
+ if (ff->isOpenTypeCFF()) {
+ cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+ }
+ delete ff;
}
- delete ff;
}
}
ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile,
- cidToGIDMap, nCIDs);
+ codeToGID ? codeToGID : cidToGIDMap,
+ codeToGID ? codeToGIDLen : nCIDs);
if (!ret) {
gfree(cidToGIDMap);
}
@@ -143,14 +150,16 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
char *fileName,
+ int fontNum,
GBool deleteFile,
- Gushort *codeToGID,
+ int *codeToGID,
int codeToGIDLen) {
FoFiTrueType *ff;
GString *tmpFileName;
FILE *tmpFile;
SplashFontFile *ret;
+ //~ this should use fontNum to load the correct font
if (!(ff = FoFiTrueType::load(fileName))) {
return NULL;
}
@@ -163,7 +172,7 @@ SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
delete ff;
fclose(tmpFile);
ret = SplashFTFontFile::loadTrueTypeFont(this, idA,
- tmpFileName->getCString(),
+ tmpFileName->getCString(), fontNum,
gTrue, codeToGID, codeToGIDLen);
if (ret) {
if (deleteFile) {
diff --git a/splash/SplashFTFontEngine.h b/splash/SplashFTFontEngine.h
index b8b9f7f..900bff2 100644
--- a/splash/SplashFTFontEngine.h
+++ b/splash/SplashFTFontEngine.h
@@ -29,30 +29,32 @@ class SplashFontFileID;
class SplashFTFontEngine {
public:
- static SplashFTFontEngine *init(GBool aaA);
+ static SplashFTFontEngine *init(GBool aaA, Guint flagsA);
~SplashFTFontEngine();
// Load fonts.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile);
SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile);
+ GBool deleteFile,
+ int *codeToGID, int codeToGIDLen);
SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile,
- Gushort *codeToGID, int codeToGIDLen);
+ int fontNum, GBool deleteFile,
+ int *codeToGID, int codeToGIDLen);
private:
- SplashFTFontEngine(GBool aaA, FT_Library libA);
+ SplashFTFontEngine(GBool aaA, Guint flagsA, FT_Library libA);
GBool aa;
+ Guint flags;
FT_Library lib;
GBool useCIDs;
diff --git a/splash/SplashFTFontFile.cc b/splash/SplashFTFontFile.cc
index dd37676..5761117 100644
--- a/splash/SplashFTFontFile.cc
+++ b/splash/SplashFTFontFile.cc
@@ -25,32 +25,32 @@ SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
- char **encA) {
+ const char **encA) {
FT_Face faceA;
- Gushort *codeToGIDA;
- char *name;
+ int *codeToGIDA;
+ const char *name;
int i;
if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
return NULL;
}
- codeToGIDA = (Gushort *)gmallocn(256, sizeof(int));
+ codeToGIDA = (int *)gmallocn(256, sizeof(int));
for (i = 0; i < 256; ++i) {
codeToGIDA[i] = 0;
if ((name = encA[i])) {
- codeToGIDA[i] = (Gushort)FT_Get_Name_Index(faceA, name);
+ codeToGIDA[i] = (int)FT_Get_Name_Index(faceA, (char *)name);
}
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
- faceA, codeToGIDA, 256, gFalse);
+ faceA, codeToGIDA, 256, gFalse, gTrue);
}
SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
- Gushort *codeToGIDA,
+ int *codeToGIDA,
int codeToGIDLenA) {
FT_Face faceA;
@@ -59,31 +59,34 @@ SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
- faceA, codeToGIDA, codeToGIDLenA, gFalse);
+ faceA, codeToGIDA, codeToGIDLenA,
+ gFalse, gFalse);
}
SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
+ int fontNum,
GBool deleteFileA,
- Gushort *codeToGIDA,
+ int *codeToGIDA,
int codeToGIDLenA) {
FT_Face faceA;
- if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
+ if (FT_New_Face(engineA->lib, fileNameA, fontNum, &faceA)) {
return NULL;
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
- faceA, codeToGIDA, codeToGIDLenA, gTrue);
+ faceA, codeToGIDA, codeToGIDLenA,
+ gTrue, gFalse);
}
SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
FT_Face faceA,
- Gushort *codeToGIDA, int codeToGIDLenA,
- GBool trueTypeA):
+ int *codeToGIDA, int codeToGIDLenA,
+ GBool trueTypeA, GBool type1A):
SplashFontFile(idA, fileNameA, deleteFileA)
{
engine = engineA;
@@ -91,6 +94,7 @@ SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
codeToGID = codeToGIDA;
codeToGIDLen = codeToGIDLenA;
trueType = trueTypeA;
+ type1 = type1A;
}
SplashFTFontFile::~SplashFTFontFile() {
diff --git a/splash/SplashFTFontFile.h b/splash/SplashFTFontFile.h
index af6a8a0..0f45e4f 100644
--- a/splash/SplashFTFontFile.h
+++ b/splash/SplashFTFontFile.h
@@ -31,16 +31,17 @@ public:
static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA, char *fileNameA,
- GBool deleteFileA, char **encA);
+ GBool deleteFileA, const char **encA);
static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA, char *fileNameA,
GBool deleteFileA,
- Gushort *codeToCIDA, int codeToGIDLenA);
+ int *codeToGIDA, int codeToGIDLenA);
static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
+ int fontNum,
GBool deleteFileA,
- Gushort *codeToGIDA,
+ int *codeToGIDA,
int codeToGIDLenA);
virtual ~SplashFTFontFile();
@@ -56,14 +57,15 @@ private:
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
FT_Face faceA,
- Gushort *codeToGIDA, int codeToGIDLenA,
- GBool trueTypeA);
+ int *codeToGIDA, int codeToGIDLenA,
+ GBool trueTypeA, GBool type1A);
SplashFTFontEngine *engine;
FT_Face face;
- Gushort *codeToGID;
+ int *codeToGID;
int codeToGIDLen;
GBool trueType;
+ GBool type1;
friend class SplashFTFont;
};
diff --git a/splash/SplashFont.cc b/splash/SplashFont.cc
index 3a30cc8..6ab2ecf 100644
--- a/splash/SplashFont.cc
+++ b/splash/SplashFont.cc
@@ -19,6 +19,13 @@
//------------------------------------------------------------------------
+// font cache size parameters
+#define splashFontCacheAssoc 8
+#define splashFontCacheMaxSets 8
+#define splashFontCacheSize (128*1024)
+
+//------------------------------------------------------------------------
+
struct SplashFontCacheTag {
int c;
short xFrac, yFrac; // x and y fractions
@@ -64,16 +71,11 @@ void SplashFont::initCache() {
}
// set up the glyph pixmap cache
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
+ cacheAssoc = splashFontCacheAssoc;
+ for (cacheSets = splashFontCacheMaxSets;
+ cacheSets > 1 &&
+ cacheSets * cacheAssoc * glyphSize > splashFontCacheSize;
+ cacheSets >>= 1) ;
cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
sizeof(SplashFontCacheTag));
diff --git a/splash/SplashFontEngine.cc b/splash/SplashFontEngine.cc
index 1c090f6..5f5ad46 100644
--- a/splash/SplashFontEngine.cc
+++ b/splash/SplashFontEngine.cc
@@ -45,6 +45,7 @@ SplashFontEngine::SplashFontEngine(
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
GBool enableFreeType,
+ Guint freeTypeFlags,
#endif
GBool aa) {
int i;
@@ -62,7 +63,7 @@ SplashFontEngine::SplashFontEngine(
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (enableFreeType) {
- ftEngine = SplashFTFontEngine::init(aa);
+ ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags);
} else {
ftEngine = NULL;
}
@@ -107,7 +108,8 @@ SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
- GBool deleteFile, char **enc) {
+ GBool deleteFile,
+ const char **enc) {
SplashFontFile *fontFile;
fontFile = NULL;
@@ -138,7 +140,7 @@ SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
SplashFontFile *fontFile;
fontFile = NULL;
@@ -169,7 +171,7 @@ SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
SplashFontFile *fontFile;
fontFile = NULL;
@@ -219,13 +221,16 @@ SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
char *fileName,
- GBool deleteFile) {
+ GBool deleteFile,
+ int *codeToGID,
+ int codeToGIDLen) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
- fontFile = ftEngine->loadOpenTypeCFFFont(idA, fileName, deleteFile);
+ fontFile = ftEngine->loadOpenTypeCFFFont(idA, fileName, deleteFile,
+ codeToGID, codeToGIDLen);
}
#endif
@@ -244,15 +249,17 @@ SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
char *fileName,
+ int fontNum,
GBool deleteFile,
- Gushort *codeToGID,
- int codeToGIDLen) {
+ int *codeToGID,
+ int codeToGIDLen,
+ char *fontName) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
- fontFile = ftEngine->loadTrueTypeFont(idA, fileName, deleteFile,
+ fontFile = ftEngine->loadTrueTypeFont(idA, fileName, fontNum, deleteFile,
codeToGID, codeToGIDLen);
}
#endif
@@ -285,7 +292,7 @@ SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
- if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.01) {
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) {
// avoid a singular (or close-to-singular) matrix
mat[0] = 0.01; mat[1] = 0;
mat[2] = 0; mat[3] = 0.01;
diff --git a/splash/SplashFontEngine.h b/splash/SplashFontEngine.h
index 6da4a74..a6d0e58 100644
--- a/splash/SplashFontEngine.h
+++ b/splash/SplashFontEngine.h
@@ -27,6 +27,10 @@ class SplashFont;
#define splashFontCacheSize 16
+#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#define splashFTNoHinting (1 << 0)
+#endif
+
//------------------------------------------------------------------------
// SplashFontEngine
//------------------------------------------------------------------------
@@ -41,6 +45,7 @@ public:
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
GBool enableFreeType,
+ Guint freeTypeFlags,
#endif
GBool aa);
@@ -52,18 +57,20 @@ public:
// Load fonts - these create new SplashFontFile objects.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile);
SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile);
+ GBool deleteFile,
+ int *codeToGID, int codeToGIDLen);
SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile,
- Gushort *codeToGID, int codeToGIDLen);
+ int fontNum, GBool deleteFile,
+ int *codeToGID, int codeToGIDLen,
+ char *fontName);
// Get a font - this does a cache lookup first, and if not found,
// creates a new SplashFont object and adds it to the cache. The
diff --git a/splash/SplashMath.h b/splash/SplashMath.h
index 1dd60dd..3b82e7a 100644
--- a/splash/SplashMath.h
+++ b/splash/SplashMath.h
@@ -8,6 +8,7 @@
#define SPLASHMATH_H
#include <aconf.h>
+
#if USE_FIXEDPONT
#include "FixedPoint.h"
#else
@@ -27,24 +28,148 @@ static inline int splashFloor(SplashCoord x) {
#if USE_FIXEDPOINT
return FixedPoint::floor(x);
#else
+#if __GNUC__ && __i386__
+ // floor() and (int)() are implemented separately, which results
+ // in changing the FPCW multiple times - so we optimize it with
+ // some inline assembly
+ Gushort oldCW, newCW, t;
+ int result;
+
+ __asm__ volatile("fldl %4\n"
+ "fnstcw %0\n"
+ "movw %0, %3\n"
+ "andw $0xf3ff, %3\n"
+ "orw $0x0400, %3\n"
+ "movw %3, %1\n" // round down
+ "fldcw %1\n"
+ "fistpl %2\n"
+ "fldcw %0\n"
+ : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
+ : "m" (x));
+ return result;
+#elif defined(WIN32) && defined(_M_IX86)
+ // floor() and (int)() are implemented separately, which results
+ // in changing the FPCW multiple times - so we optimize it with
+ // some inline assembly
+ Gushort oldCW, newCW;
+ int result;
+
+ __asm fld QWORD PTR x
+ __asm fnstcw WORD PTR oldCW
+ __asm mov ax, WORD PTR oldCW
+ __asm and ax, 0xf3ff
+ __asm or ax, 0x0400
+ __asm mov WORD PTR newCW, ax // round down
+ __asm fldcw WORD PTR newCW
+ __asm fistp DWORD PTR result
+ __asm fldcw WORD PTR oldCW
+ return result;
+#else
return (int)floor(x);
#endif
+#endif
}
static inline int splashCeil(SplashCoord x) {
#if USE_FIXEDPOINT
return FixedPoint::ceil(x);
#else
+#if __GNUC__ && __i386__
+ // ceil() and (int)() are implemented separately, which results
+ // in changing the FPCW multiple times - so we optimize it with
+ // some inline assembly
+ Gushort oldCW, newCW, t;
+ int result;
+
+ __asm__ volatile("fldl %4\n"
+ "fnstcw %0\n"
+ "movw %0, %3\n"
+ "andw $0xf3ff, %3\n"
+ "orw $0x0800, %3\n"
+ "movw %3, %1\n" // round up
+ "fldcw %1\n"
+ "fistpl %2\n"
+ "fldcw %0\n"
+ : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
+ : "m" (x));
+ return result;
+#elif defined(WIN32) && defined(_M_IX86)
+ // ceil() and (int)() are implemented separately, which results
+ // in changing the FPCW multiple times - so we optimize it with
+ // some inline assembly
+ Gushort oldCW, newCW;
+ int result;
+
+ __asm fld QWORD PTR x
+ __asm fnstcw WORD PTR oldCW
+ __asm mov ax, WORD PTR oldCW
+ __asm and ax, 0xf3ff
+ __asm or ax, 0x0800
+ __asm mov WORD PTR newCW, ax // round up
+ __asm fldcw WORD PTR newCW
+ __asm fistp DWORD PTR result
+ __asm fldcw WORD PTR oldCW
+ return result;
+#else
return (int)ceil(x);
#endif
+#endif
}
static inline int splashRound(SplashCoord x) {
#if USE_FIXEDPOINT
return FixedPoint::round(x);
#else
+#if __GNUC__ && __i386__
+ // this could use round-to-nearest mode and avoid the "+0.5",
+ // but that produces slightly different results (because i+0.5
+ // sometimes rounds up and sometimes down using the even rule)
+ Gushort oldCW, newCW, t;
+ int result;
+
+ x += 0.5;
+ __asm__ volatile("fldl %4\n"
+ "fnstcw %0\n"
+ "movw %0, %3\n"
+ "andw $0xf3ff, %3\n"
+ "orw $0x0400, %3\n"
+ "movw %3, %1\n" // round down
+ "fldcw %1\n"
+ "fistpl %2\n"
+ "fldcw %0\n"
+ : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
+ : "m" (x));
+ return result;
+#elif defined(WIN32) && defined(_M_IX86)
+ // this could use round-to-nearest mode and avoid the "+0.5",
+ // but that produces slightly different results (because i+0.5
+ // sometimes rounds up and sometimes down using the even rule)
+ Gushort oldCW, newCW;
+ int result;
+
+ x += 0.5;
+ __asm fld QWORD PTR x
+ __asm fnstcw WORD PTR oldCW
+ __asm mov ax, WORD PTR oldCW
+ __asm and ax, 0xf3ff
+ __asm or ax, 0x0400
+ __asm mov WORD PTR newCW, ax // round down
+ __asm fldcw WORD PTR newCW
+ __asm fistp DWORD PTR result
+ __asm fldcw WORD PTR oldCW
+ return result;
+#else
return (int)floor(x + 0.5);
#endif
+#endif
+}
+
+static inline SplashCoord splashAvg(SplashCoord x, SplashCoord y) {
+#if USE_FIXEDPOINT
+ return FixedPoint::avg(x, y);
+#else
+ return 0.5 * (x + y);
+#endif
}
static inline SplashCoord splashSqrt(SplashCoord x) {
@@ -71,19 +196,31 @@ static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
#if USE_FIXEDPOINT
// this handles the situation where dx*dx or dy*dy is too large to
// fit in the 16.16 fixed point format
- SplashCoord dxa, dya;
+ SplashCoord dxa, dya, d;
dxa = splashAbs(dx);
dya = splashAbs(dy);
if (dxa == 0 && dya == 0) {
return 0;
} else if (dxa > dya) {
- return dxa * FixedPoint::sqrt(dya / dxa + 1);
+ d = dya / dxa;
+ return dxa * FixedPoint::sqrt(d*d + 1);
} else {
- return dya * FixedPoint::sqrt(dxa / dya + 1);
+ d = dxa / dya;
+ return dya * FixedPoint::sqrt(d*d + 1);
}
#else
return sqrt(dx * dx + dy * dy);
#endif
}
+static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12,
+ SplashCoord m21, SplashCoord m22,
+ SplashCoord epsilon) {
+#if USE_FIXEDPOINT
+ return FixedPoint::checkDet(m11, m12, m21, m22, epsilon);
+#else
+ return fabs(m11 * m22 - m12 * m21) >= epsilon;
+#endif
+}
+
#endif
diff --git a/splash/SplashPath.cc b/splash/SplashPath.cc
index e3a8927..b4249ed 100644
--- a/splash/SplashPath.cc
+++ b/splash/SplashPath.cc
@@ -136,11 +136,12 @@ SplashError SplashPath::curveTo(SplashCoord x1, SplashCoord y1,
return splashOk;
}
-SplashError SplashPath::close() {
+SplashError SplashPath::close(GBool force) {
if (noCurrentPoint()) {
return splashErrNoCurPt;
}
- if (curSubpath == length - 1 ||
+ if (force ||
+ curSubpath == length - 1 ||
pts[length - 1].x != pts[curSubpath].x ||
pts[length - 1].y != pts[curSubpath].y) {
lineTo(pts[curSubpath].x, pts[curSubpath].y);
diff --git a/splash/SplashPath.h b/splash/SplashPath.h
index b63ee5d..aae51f2 100644
--- a/splash/SplashPath.h
+++ b/splash/SplashPath.h
@@ -79,8 +79,10 @@ public:
SplashCoord x2, SplashCoord y2,
SplashCoord x3, SplashCoord y3);
- // Close the last subpath, adding a line segment if necessary.
- SplashError close();
+ // Close the last subpath, adding a line segment if necessary. If
+ // <force> is true, this adds a line segment even if the current
+ // point is equal to the first point in the subpath.
+ SplashError close(GBool force = gFalse);
// Add a stroke adjustment hint. The controlling segments are
// <ctrl0> and <ctrl1> (where segments are identified by their first
diff --git a/splash/SplashScreen.cc b/splash/SplashScreen.cc
index 318629d..f717173 100644
--- a/splash/SplashScreen.cc
+++ b/splash/SplashScreen.cc
@@ -12,6 +12,9 @@
#include <stdlib.h>
#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
#include "gmem.h"
#include "SplashMath.h"
#include "SplashScreen.h"
@@ -34,10 +37,22 @@ struct SplashScreenPoint {
int dist;
};
+#if HAVE_STD_SORT
+
+struct cmpDistancesFunctor {
+ bool operator()(const SplashScreenPoint &p0, const SplashScreenPoint &p1) {
+ return p0.dist < p1.dist;
+ }
+};
+
+#else // HAVE_STD_SORT
+
static int cmpDistances(const void *p0, const void *p1) {
return ((SplashScreenPoint *)p0)->dist - ((SplashScreenPoint *)p1)->dist;
}
+#endif
+
//------------------------------------------------------------------------
// SplashScreen
//------------------------------------------------------------------------
@@ -48,44 +63,41 @@ static int cmpDistances(const void *p0, const void *p1) {
// threshold matrix using recursive tesselation. Gamma correction
// (gamma = 1 / 1.33) is also computed here.
SplashScreen::SplashScreen(SplashScreenParams *params) {
- Guchar u, black, white;
- int i;
+ Guchar u;
+ int black, white, i;
if (!params) {
params = &defaultParams;
}
+ // size must be a power of 2, and at least 2
+ for (size = 2, log2Size = 1; size < params->size; size <<= 1, ++log2Size) ;
+
switch (params->type) {
case splashScreenDispersed:
- // size must be a power of 2
- for (size = 1; size < params->size; size <<= 1) ;
mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
buildDispersedMatrix(size/2, size/2, 1, size/2, 1);
break;
case splashScreenClustered:
- // size must be even
- size = (params->size >> 1) << 1;
- if (size < 2) {
- size = 2;
- }
mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
buildClusteredMatrix();
break;
case splashScreenStochasticClustered:
// size must be at least 2*r
- if (params->size < 2 * params->dotRadius) {
- size = 2 * params->dotRadius;
- } else {
- size = params->size;
+ while (size < (params->dotRadius << 1)) {
+ size <<= 1;
+ ++log2Size;
}
mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
buildSCDMatrix(params->dotRadius);
break;
}
+ sizeM1 = size - 1;
+
// do gamma correction and compute minVal/maxVal
minVal = 255;
maxVal = 0;
@@ -101,9 +113,9 @@ SplashScreen::SplashScreen(SplashScreenParams *params) {
u = splashRound((SplashCoord)255.0 *
splashPow((SplashCoord)mat[i] / 255.0, params->gamma));
if (u < black) {
- u = black;
+ u = (Guchar)black;
} else if (u >= white) {
- u = white;
+ u = (Guchar)white;
}
mat[i] = u;
if (u < minVal) {
@@ -118,7 +130,7 @@ void SplashScreen::buildDispersedMatrix(int i, int j, int val,
int delta, int offset) {
if (delta == 0) {
// map values in [1, size^2] --> [1, 255]
- mat[i * size + j] = 1 + (254 * (val - 1)) / (size * size - 1);
+ mat[(i << log2Size) + j] = 1 + (254 * (val - 1)) / (size * size - 1);
} else {
buildDispersedMatrix(i, j,
val, delta / 2, 4*offset);
@@ -142,7 +154,7 @@ void SplashScreen::buildClusteredMatrix() {
// initialize the threshold matrix
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
- mat[y * size + x] = 0;
+ mat[(y << log2Size) + x] = 0;
}
}
@@ -174,14 +186,12 @@ void SplashScreen::buildClusteredMatrix() {
}
// build the threshold matrix
- minVal = 1;
- maxVal = 0;
x1 = y1 = 0; // make gcc happy
for (i = 0; i < size * size2; ++i) {
d = -1;
for (y = 0; y < size; ++y) {
for (x = 0; x < size2; ++x) {
- if (mat[y * size + x] == 0 &&
+ if (mat[(y << log2Size) + x] == 0 &&
dist[y * size2 + x] > d) {
x1 = x;
y1 = y;
@@ -191,12 +201,12 @@ void SplashScreen::buildClusteredMatrix() {
}
// map values in [0, 2*size*size2-1] --> [1, 255]
val = 1 + (254 * (2*i)) / (2*size*size2 - 1);
- mat[y1 * size + x1] = val;
+ mat[(y1 << log2Size) + x1] = val;
val = 1 + (254 * (2*i+1)) / (2*size*size2 - 1);
if (y1 < size2) {
- mat[(y1 + size2) * size + x1 + size2] = val;
+ mat[((y1 + size2) << log2Size) + x1 + size2] = val;
} else {
- mat[(y1 - size2) * size + x1 + size2] = val;
+ mat[((y1 - size2) << log2Size) + x1 + size2] = val;
}
}
@@ -264,7 +274,7 @@ void SplashScreen::buildSCDMatrix(int r) {
grid = (char *)gmallocn(size * size, sizeof(char));
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
- grid[y*size + x] = 0;
+ grid[(y << log2Size) + x] = 0;
}
}
@@ -275,7 +285,7 @@ void SplashScreen::buildSCDMatrix(int r) {
for (i = 0; i < size * size; ++i) {
x = pts[i].x;
y = pts[i].y;
- if (!grid[y*size + x]) {
+ if (!grid[(y << log2Size) + x]) {
if (dotsLen == dotsSize) {
dotsSize *= 2;
dots = (SplashScreenPoint *)greallocn(dots, dotsSize,
@@ -289,10 +299,10 @@ void SplashScreen::buildSCDMatrix(int r) {
if (tmpl[yy*(r+1) + xx]) {
x0 = (x + xx) % size;
x1 = (x - xx + size) % size;
- grid[y0*size + x0] = 1;
- grid[y0*size + x1] = 1;
- grid[y1*size + x0] = 1;
- grid[y1*size + x1] = 1;
+ grid[(y0 << log2Size) + x0] = 1;
+ grid[(y0 << log2Size) + x1] = 1;
+ grid[(y1 << log2Size) + x0] = 1;
+ grid[(y1 << log2Size) + x1] = 1;
}
}
}
@@ -316,8 +326,8 @@ void SplashScreen::buildSCDMatrix(int r) {
dMin = d;
}
}
- region[y*size + x] = iMin;
- dist[y*size + x] = dMin;
+ region[(y << log2Size) + x] = iMin;
+ dist[(y << log2Size) + x] = dMin;
}
}
@@ -326,7 +336,7 @@ void SplashScreen::buildSCDMatrix(int r) {
n = 0;
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
- if (region[y*size + x] == i) {
+ if (region[(y << log2Size) + x] == i) {
pts[n].x = x;
pts[n].y = y;
pts[n].dist = distance(dots[i].x, dots[i].y, x, y);
@@ -334,10 +344,14 @@ void SplashScreen::buildSCDMatrix(int r) {
}
}
}
+#if HAVE_STD_SORT
+ std::sort(pts, pts + n, cmpDistancesFunctor());
+#else
qsort(pts, n, sizeof(SplashScreenPoint), &cmpDistances);
+#endif
for (j = 0; j < n; ++j) {
// map values in [0 .. n-1] --> [255 .. 1]
- mat[pts[j].y * size + pts[j].x] = 255 - (254 * j) / (n - 1);
+ mat[(pts[j].y << log2Size) + pts[j].x] = 255 - (254 * j) / (n - 1);
}
}
@@ -350,6 +364,8 @@ void SplashScreen::buildSCDMatrix(int r) {
SplashScreen::SplashScreen(SplashScreen *screen) {
size = screen->size;
+ sizeM1 = screen->sizeM1;
+ log2Size = screen->log2Size;
mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
memcpy(mat, screen->mat, size * size * sizeof(Guchar));
minVal = screen->minVal;
@@ -359,25 +375,3 @@ SplashScreen::SplashScreen(SplashScreen *screen) {
SplashScreen::~SplashScreen() {
gfree(mat);
}
-
-int SplashScreen::test(int x, int y, Guchar value) {
- int xx, yy;
-
- if (value < minVal) {
- return 0;
- }
- if (value >= maxVal) {
- return 1;
- }
- if ((xx = x % size) < 0) {
- xx = -xx;
- }
- if ((yy = y % size) < 0) {
- yy = -yy;
- }
- return value < mat[yy * size + xx] ? 0 : 1;
-}
-
-GBool SplashScreen::isStatic(Guchar value) {
- return value < minVal || value >= maxVal;
-}
diff --git a/splash/SplashScreen.h b/splash/SplashScreen.h
index 2baa9b5..708c37f 100644
--- a/splash/SplashScreen.h
+++ b/splash/SplashScreen.h
@@ -30,12 +30,17 @@ public:
// Return the computed pixel value (0=black, 1=white) for the gray
// level <value> at (<x>, <y>).
- int test(int x, int y, Guchar value);
+ int test(int x, int y, Guchar value) {
+ int xx, yy;
+ xx = x & sizeM1;
+ yy = y & sizeM1;
+ return value < mat[(yy << log2Size) + xx] ? 0 : 1;
+ }
// Returns true if value is above the white threshold or below the
// black threshold, i.e., if the corresponding halftone will be
// solid white or black.
- GBool isStatic(Guchar value);
+ GBool isStatic(Guchar value) { return value < minVal || value >= maxVal; }
private:
@@ -47,6 +52,8 @@ private:
Guchar *mat; // threshold matrix
int size; // size of the threshold matrix
+ int sizeM1; // size - 1
+ int log2Size; // log2(size)
Guchar minVal; // any pixel value below minVal generates
// solid black
Guchar maxVal; // any pixel value above maxVal generates
diff --git a/splash/SplashState.cc b/splash/SplashState.cc
index e2c34c4..e6dde61 100644
--- a/splash/SplashState.cc
+++ b/splash/SplashState.cc
@@ -24,12 +24,16 @@
// number of components in each color mode
int splashColorModeNComps[] = {
- 1, 1, 3, 3, 4
+ 1, 1, 3, 3
+#if SPLASH_CMYK
+ , 4
+#endif
};
SplashState::SplashState(int width, int height, GBool vectorAntialias,
SplashScreenParams *screenParams) {
SplashColor color;
+ int i;
matrix[0] = 1; matrix[1] = 0;
matrix[2] = 0; matrix[3] = 1;
@@ -50,16 +54,28 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
lineDashLength = 0;
lineDashPhase = 0;
strokeAdjust = gFalse;
- clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias);
+ clip = new SplashClip(0, 0, width, height, vectorAntialias);
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
+ for (i = 0; i < 256; ++i) {
+ rgbTransferR[i] = (Guchar)i;
+ rgbTransferG[i] = (Guchar)i;
+ rgbTransferB[i] = (Guchar)i;
+ grayTransfer[i] = (Guchar)i;
+ cmykTransferC[i] = (Guchar)i;
+ cmykTransferM[i] = (Guchar)i;
+ cmykTransferY[i] = (Guchar)i;
+ cmykTransferK[i] = (Guchar)i;
+ }
+ overprintMask = 0xffffffff;
next = NULL;
}
SplashState::SplashState(int width, int height, GBool vectorAntialias,
SplashScreen *screenA) {
SplashColor color;
+ int i;
matrix[0] = 1; matrix[1] = 0;
matrix[2] = 0; matrix[3] = 1;
@@ -80,10 +96,21 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
lineDashLength = 0;
lineDashPhase = 0;
strokeAdjust = gFalse;
- clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias);
+ clip = new SplashClip(0, 0, width, height, vectorAntialias);
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
+ for (i = 0; i < 256; ++i) {
+ rgbTransferR[i] = (Guchar)i;
+ rgbTransferG[i] = (Guchar)i;
+ rgbTransferB[i] = (Guchar)i;
+ grayTransfer[i] = (Guchar)i;
+ cmykTransferC[i] = (Guchar)i;
+ cmykTransferM[i] = (Guchar)i;
+ cmykTransferY[i] = (Guchar)i;
+ cmykTransferK[i] = (Guchar)i;
+ }
+ overprintMask = 0xffffffff;
next = NULL;
}
@@ -114,6 +141,15 @@ SplashState::SplashState(SplashState *state) {
softMask = state->softMask;
deleteSoftMask = gFalse;
inNonIsolatedGroup = state->inNonIsolatedGroup;
+ memcpy(rgbTransferR, state->rgbTransferR, 256);
+ memcpy(rgbTransferG, state->rgbTransferG, 256);
+ memcpy(rgbTransferB, state->rgbTransferB, 256);
+ memcpy(grayTransfer, state->grayTransfer, 256);
+ memcpy(cmykTransferC, state->cmykTransferC, 256);
+ memcpy(cmykTransferM, state->cmykTransferM, 256);
+ memcpy(cmykTransferY, state->cmykTransferY, 256);
+ memcpy(cmykTransferK, state->cmykTransferK, 256);
+ overprintMask = state->overprintMask;
next = NULL;
}
@@ -163,3 +199,19 @@ void SplashState::setSoftMask(SplashBitmap *softMaskA) {
softMask = softMaskA;
deleteSoftMask = gTrue;
}
+
+void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
+ Guchar *gray) {
+ int i;
+
+ memcpy(rgbTransferR, red, 256);
+ memcpy(rgbTransferG, green, 256);
+ memcpy(rgbTransferB, blue, 256);
+ memcpy(grayTransfer, gray, 256);
+ for (i = 0; i < 256; ++i) {
+ cmykTransferC[i] = 255 - rgbTransferR[255 - i];
+ cmykTransferM[i] = 255 - rgbTransferG[255 - i];
+ cmykTransferY[i] = 255 - rgbTransferB[255 - i];
+ cmykTransferK[i] = 255 - grayTransfer[255 - i];
+ }
+}
diff --git a/splash/SplashState.h b/splash/SplashState.h
index 1f5a88d..0d1b6c5 100644
--- a/splash/SplashState.h
+++ b/splash/SplashState.h
@@ -70,6 +70,9 @@ public:
// Set the soft mask bitmap.
void setSoftMask(SplashBitmap *softMaskA);
+ // Set the transfer function.
+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
+
private:
SplashState(SplashState *state);
@@ -94,6 +97,15 @@ private:
SplashBitmap *softMask;
GBool deleteSoftMask;
GBool inNonIsolatedGroup;
+ Guchar rgbTransferR[256],
+ rgbTransferG[256],
+ rgbTransferB[256];
+ Guchar grayTransfer[256];
+ Guchar cmykTransferC[256],
+ cmykTransferM[256],
+ cmykTransferY[256],
+ cmykTransferK[256];
+ Guint overprintMask;
SplashState *next; // used by Splash class
diff --git a/splash/SplashT1Font.cc b/splash/SplashT1Font.cc
index 8219596..703aacf 100644
--- a/splash/SplashT1Font.cc
+++ b/splash/SplashT1Font.cc
@@ -76,7 +76,7 @@ SplashT1Font::SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA,
outlineID = -1;
// compute font size
- size = (float)splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
+ size = (float)splashDist(0, 0, mat[2], mat[3]);
// transform the four corners of the font bounding box -- the min
// and max values form the bounding box of the transformed font
@@ -220,13 +220,12 @@ SplashPath *SplashT1Font::getGlyphPath(int c) {
T1_OUTLINE *outline;
T1_PATHSEGMENT *seg;
T1_BEZIERSEGMENT *bez;
- SplashCoord x, y, x1, y1;
+ int x, y, x1, y1;
GBool needClose;
if (outlineID < 0) {
outlineID = T1_CopyFont(((SplashT1FontFile *)fontFile)->t1libID);
- outlineSize = (float)splashSqrt(textMat[2]*textMat[2] +
- textMat[3]*textMat[3]);
+ outlineSize = (float)splashDist(0, 0, textMat[2], textMat[3]);
matrix.cxx = (double)textMat[0] / outlineSize;
matrix.cxy = (double)textMat[1] / outlineSize;
matrix.cyx = (double)textMat[2] / outlineSize;
@@ -240,8 +239,11 @@ SplashPath *SplashT1Font::getGlyphPath(int c) {
path = new SplashPath();
if ((outline = T1_GetCharOutline(outlineID, c, outlineSize, NULL))) {
- x = 0;
- y = 0;
+ // NB: t1lib uses integer coordinates here; we keep a running
+ // (x,y) total as integers, so that the final point in the path is
+ // exactly the same as the first point, thus avoiding weird
+ // mitered join glitches
+ x = y = 0;
needClose = gFalse;
for (seg = outline; seg; seg = seg->link) {
switch (seg->type) {
@@ -250,25 +252,26 @@ SplashPath *SplashT1Font::getGlyphPath(int c) {
path->close();
needClose = gFalse;
}
- x += seg->dest.x * outlineMul;
- y += seg->dest.y * outlineMul;
- path->moveTo(x, -y);
+ x += seg->dest.x;
+ y += seg->dest.y;
+ path->moveTo(outlineMul * x, -outlineMul * y);
break;
case T1_PATHTYPE_LINE:
- x += seg->dest.x * outlineMul;
- y += seg->dest.y * outlineMul;
- path->lineTo(x, -y);
+ x += seg->dest.x;
+ y += seg->dest.y;
+ path->lineTo(outlineMul * x, -outlineMul * y);
needClose = gTrue;
break;
case T1_PATHTYPE_BEZIER:
bez = (T1_BEZIERSEGMENT *)seg;
- x1 = x + (SplashCoord)(bez->dest.x * outlineMul);
- y1 = y + (SplashCoord)(bez->dest.y * outlineMul);
- path->curveTo(x + (SplashCoord)(bez->B.x * outlineMul),
- -(y + (SplashCoord)(bez->B.y * outlineMul)),
- x + (SplashCoord)(bez->C.x * outlineMul),
- -(y + (SplashCoord)(bez->C.y * outlineMul)),
- x1, -y1);
+ x1 = x + bez->dest.x;
+ y1 = y + bez->dest.y;
+ path->curveTo(outlineMul * (x + bez->B.x),
+ -outlineMul * (y + bez->B.y),
+ outlineMul * (x + bez->C.x),
+ -outlineMul * (y + bez->C.y),
+ outlineMul * x1,
+ -outlineMul * y1);
x = x1;
y = y1;
needClose = gTrue;
diff --git a/splash/SplashT1FontEngine.cc b/splash/SplashT1FontEngine.cc
index ca1453a..277e2fc 100644
--- a/splash/SplashT1FontEngine.cc
+++ b/splash/SplashT1FontEngine.cc
@@ -36,7 +36,7 @@ int SplashT1FontEngine::t1libInitCount = 0;
//------------------------------------------------------------------------
-static void fileWrite(void *stream, char *data, int len) {
+static void fileWrite(void *stream, const char *data, int len) {
fwrite(data, 1, len, (FILE *)stream);
}
@@ -84,14 +84,14 @@ SplashT1FontEngine::~SplashT1FontEngine() {
SplashFontFile *SplashT1FontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
return SplashT1FontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashT1FontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
- char **enc) {
+ const char **enc) {
FoFiType1C *ff;
GString *tmpFileName;
FILE *tmpFile;
diff --git a/splash/SplashT1FontEngine.h b/splash/SplashT1FontEngine.h
index 57a0448..8942b85 100644
--- a/splash/SplashT1FontEngine.h
+++ b/splash/SplashT1FontEngine.h
@@ -33,9 +33,9 @@ public:
// Load fonts.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
- GBool deleteFile, char **enc);
+ GBool deleteFile, const char **enc);
private:
diff --git a/splash/SplashT1FontFile.cc b/splash/SplashT1FontFile.cc
index 0dbb8f0..8cec742 100644
--- a/splash/SplashT1FontFile.cc
+++ b/splash/SplashT1FontFile.cc
@@ -27,9 +27,9 @@ SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
- char **encA) {
+ const char **encA) {
int t1libIDA;
- char **encTmp;
+ const char **encTmp;
char *encStrTmp;
int encStrSize;
char *encPtr;
@@ -48,7 +48,7 @@ SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA,
encStrSize += strlen(encA[i]) + 1;
}
}
- encTmp = (char **)gmallocn(257, sizeof(char *));
+ encTmp = (const char **)gmallocn(257, sizeof(char *));
encStrTmp = (char *)gmallocn(encStrSize, sizeof(char));
encPtr = encStrTmp;
for (i = 0; i < 256; ++i) {
@@ -61,7 +61,7 @@ SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA,
}
}
encTmp[256] = "custom";
- T1_ReencodeFont(t1libIDA, encTmp);
+ T1_ReencodeFont(t1libIDA, (char **)encTmp);
return new SplashT1FontFile(engineA, idA, fileNameA, deleteFileA,
t1libIDA, encTmp, encStrTmp);
@@ -70,7 +70,8 @@ SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA,
SplashT1FontFile::SplashT1FontFile(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
- int t1libIDA, char **encA, char *encStrA):
+ int t1libIDA, const char **encA,
+ char *encStrA):
SplashFontFile(idA, fileNameA, deleteFileA)
{
engine = engineA;
diff --git a/splash/SplashT1FontFile.h b/splash/SplashT1FontFile.h
index 69c9caf..57de84d 100644
--- a/splash/SplashT1FontFile.h
+++ b/splash/SplashT1FontFile.h
@@ -29,7 +29,7 @@ public:
static SplashFontFile *loadType1Font(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
- char **encA);
+ const char **encA);
virtual ~SplashT1FontFile();
@@ -43,11 +43,11 @@ private:
SplashT1FontFile(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
- int t1libIDA, char **encA, char *encStrA);
+ int t1libIDA, const char **encA, char *encStrA);
SplashT1FontEngine *engine;
int t1libID; // t1lib font ID
- char **enc;
+ const char **enc;
char *encStr;
friend class SplashT1Font;
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index 35551b9..6eb2607 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -52,10 +52,10 @@ enum SplashColorMode {
extern int splashColorModeNComps[];
// max number of components in any SplashColor
+#define splashMaxColorComps 3
#if SPLASH_CMYK
+# undef splashMaxColorComps
# define splashMaxColorComps 4
-#else
-# define splashMaxColorComps 3
#endif
typedef Guchar SplashColor[splashMaxColorComps];
diff --git a/splash/SplashXPath.cc b/splash/SplashXPath.cc
index da296b1..6ed2f4b 100644
--- a/splash/SplashXPath.cc
+++ b/splash/SplashXPath.cc
@@ -12,6 +12,9 @@
#include <stdlib.h>
#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
#include "gmem.h"
#include "SplashMath.h"
#include "SplashPath.h"
@@ -49,19 +52,13 @@ inline void SplashXPath::transform(SplashCoord *matrix,
// SplashXPath
//------------------------------------------------------------------------
-SplashXPath::SplashXPath() {
- segs = NULL;
- length = size = 0;
-}
-
SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
SplashCoord flatness, GBool closeSubpaths) {
SplashPathHint *hint;
SplashXPathPoint *pts;
SplashXPathAdjust *adjusts, *adjust;
SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp;
- SplashCoord adj0, adj1, w;
- int ww;
+ SplashCoord adj0, adj1;
int curSubpath, curSubpathX, i, j;
// transform the points
@@ -98,19 +95,24 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
adj0 = adj1;
adj1 = x0;
}
- w = adj1 - adj0;
- ww = splashRound(w);
- if (ww == 0) {
- ww = 1;
- }
adjusts[i].x0a = adj0 - 0.01;
adjusts[i].x0b = adj0 + 0.01;
adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - 0.01;
adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + 0.01;
adjusts[i].x1a = adj1 - 0.01;
adjusts[i].x1b = adj1 + 0.01;
- adjusts[i].x0 = (SplashCoord)splashRound(adj0);
- adjusts[i].x1 = adjusts[i].x0 + ww - 0.01;
+ // rounding both edge coordinates can result in lines of
+ // different widths (e.g., adj=10.1, adj1=11.3 --> x0=10, x1=11;
+ // adj0=10.4, adj1=11.6 --> x0=10, x1=12), but it has the
+ // benefit of making adjacent strokes/fills line up without any
+ // gaps between them
+ x0 = splashRound(adj0);
+ x1 = splashRound(adj1);
+ if (x1 == x0) {
+ x1 = x1 + 1;
+ }
+ adjusts[i].x0 = (SplashCoord)x0;
+ adjusts[i].x1 = (SplashCoord)x1 - 0.01;
adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1);
adjusts[i].firstPt = hint->firstPt;
adjusts[i].lastPt = hint->lastPt;
@@ -178,15 +180,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
} else {
x1 = pts[i].x;
y1 = pts[i].y;
- addSegment(x0, y0, x1, y1,
- path->flags[i-1] & splashPathFirst,
- path->flags[i] & splashPathLast,
- !closeSubpaths &&
- (path->flags[i-1] & splashPathFirst) &&
- !(path->flags[i-1] & splashPathClosed),
- !closeSubpaths &&
- (path->flags[i] & splashPathLast) &&
- !(path->flags[i] & splashPathClosed));
+ addSegment(x0, y0, x1, y1);
x0 = x1;
y0 = y1;
++i;
@@ -197,8 +191,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
(path->flags[i-1] & splashPathLast) &&
(pts[i-1].x != pts[curSubpath].x ||
pts[i-1].y != pts[curSubpath].y)) {
- addSegment(x0, y0, xsp, ysp,
- gFalse, gTrue, gFalse, gFalse);
+ addSegment(x0, y0, xsp, ysp);
}
}
}
@@ -270,7 +263,11 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
SplashCoord dx, dy, mx, my, d1, d2, flatness2;
int p1, p2, p3;
+#if USE_FIXEDPOINT
+ flatness2 = flatness;
+#else
flatness2 = flatness * flatness;
+#endif
// initial segment
p1 = 0;
@@ -296,21 +293,22 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
// line)
mx = (xl0 + xr3) * 0.5;
my = (yl0 + yr3) * 0.5;
+#if USE_FIXEDPOINT
+ d1 = splashDist(xx1, yy1, mx, my);
+ d2 = splashDist(xx2, yy2, mx, my);
+#else
dx = xx1 - mx;
dy = yy1 - my;
d1 = dx*dx + dy*dy;
dx = xx2 - mx;
dy = yy2 - my;
d2 = dx*dx + dy*dy;
+#endif
// if the curve is flat enough, or no more subdivisions are
// allowed, add the straight line segment
if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) {
- addSegment(xl0, yl0, xr3, yr3,
- p1 == 0 && first,
- p2 == splashMaxCurveSplits && last,
- p1 == 0 && end0,
- p2 == splashMaxCurveSplits && end1);
+ addSegment(xl0, yl0, xr3, yr3);
p1 = p2;
// otherwise, subdivide the curve
@@ -341,26 +339,13 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
}
void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- GBool first, GBool last, GBool end0, GBool end1) {
+ SplashCoord x1, SplashCoord y1) {
grow(1);
segs[length].x0 = x0;
segs[length].y0 = y0;
segs[length].x1 = x1;
segs[length].y1 = y1;
segs[length].flags = 0;
- if (first) {
- segs[length].flags |= splashXPathFirst;
- }
- if (last) {
- segs[length].flags |= splashXPathLast;
- }
- if (end0) {
- segs[length].flags |= splashXPathEnd0;
- }
- if (end1) {
- segs[length].flags |= splashXPathEnd1;
- }
if (y1 == y0) {
segs[length].dxdy = segs[length].dydx = 0;
segs[length].flags |= splashXPathHoriz;
@@ -393,6 +378,44 @@ void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
++length;
}
+void SplashXPath::aaScale() {
+ SplashXPathSeg *seg;
+ int i;
+
+ for (i = 0, seg = segs; i < length; ++i, ++seg) {
+ seg->x0 *= splashAASize;
+ seg->y0 *= splashAASize;
+ seg->x1 *= splashAASize;
+ seg->y1 *= splashAASize;
+ }
+}
+
+#if HAVE_STD_SORT
+
+struct cmpXPathSegsFunctor {
+ bool operator()(const SplashXPathSeg &seg0, const SplashXPathSeg &seg1) {
+ SplashCoord x0, y0, x1, y1;
+
+ if (seg0.flags & splashXPathFlip) {
+ x0 = seg0.x1;
+ y0 = seg0.y1;
+ } else {
+ x0 = seg0.x0;
+ y0 = seg0.y0;
+ }
+ if (seg1.flags & splashXPathFlip) {
+ x1 = seg1.x1;
+ y1 = seg1.y1;
+ } else {
+ x1 = seg1.x0;
+ y1 = seg1.y0;
+ }
+ return (y0 != y1) ? (y0 < y1) : (x0 < x1);
+ }
+};
+
+#else // HAVE_STD_SORT
+
static int cmpXPathSegs(const void *arg0, const void *arg1) {
SplashXPathSeg *seg0 = (SplashXPathSeg *)arg0;
SplashXPathSeg *seg1 = (SplashXPathSeg *)arg1;
@@ -421,18 +444,12 @@ static int cmpXPathSegs(const void *arg0, const void *arg1) {
return 0;
}
-void SplashXPath::aaScale() {
- SplashXPathSeg *seg;
- int i;
-
- for (i = 0, seg = segs; i < length; ++i, ++seg) {
- seg->x0 *= splashAASize;
- seg->y0 *= splashAASize;
- seg->x1 *= splashAASize;
- seg->y1 *= splashAASize;
- }
-}
+#endif // HAVE_STD_SORT
void SplashXPath::sort() {
+#if HAVE_STD_SORT
+ std::sort(segs, segs + length, cmpXPathSegsFunctor());
+#else
qsort(segs, length, sizeof(SplashXPathSeg), &cmpXPathSegs);
+#endif
}
diff --git a/splash/SplashXPath.h b/splash/SplashXPath.h
index 43276b8..4e06d82 100644
--- a/splash/SplashXPath.h
+++ b/splash/SplashXPath.h
@@ -34,15 +34,11 @@ struct SplashXPathSeg {
Guint flags;
};
-#define splashXPathFirst 0x01 // first segment of a subpath
-#define splashXPathLast 0x02 // last segment of a subpath
-#define splashXPathEnd0 0x04 // first endpoint is end of an open subpath
-#define splashXPathEnd1 0x08 // second endpoint is end of an open subpath
-#define splashXPathHoriz 0x10 // segment is vertical (y0 == y1)
+#define splashXPathHoriz 0x01 // segment is vertical (y0 == y1)
// (dxdy is undef)
-#define splashXPathVert 0x20 // segment is horizontal (x0 == x1)
+#define splashXPathVert 0x02 // segment is horizontal (x0 == x1)
// (dydx is undef)
-#define splashXPathFlip 0x40 // y0 > y1
+#define splashXPathFlip 0x04 // y0 > y1
//------------------------------------------------------------------------
// SplashXPath
@@ -72,7 +68,6 @@ public:
private:
- SplashXPath();
SplashXPath(SplashXPath *xPath);
void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
SplashCoord *xo, SplashCoord *yo);
@@ -86,8 +81,7 @@ private:
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1);
void addSegment(SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- GBool first, GBool last, GBool end0, GBool end1);
+ SplashCoord x1, SplashCoord y1);
SplashXPathSeg *segs;
int length, size; // length and size of segs array
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index d13206b..abe4593 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -12,6 +12,9 @@
#include <stdlib.h>
#include <string.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
#include "gmem.h"
#include "SplashMath.h"
#include "SplashXPath.h"
@@ -21,25 +24,47 @@
//------------------------------------------------------------------------
struct SplashIntersect {
+ int y;
int x0, x1; // intersection of segment with [y, y+1)
int count; // EO/NZWN counter increment
};
+#if HAVE_STD_SORT
+
+struct cmpIntersectFunctor {
+ bool operator()(const SplashIntersect &i0, const SplashIntersect &i1) {
+ return (i0.y != i1.y) ? (i0.y < i1.y) : (i0.x0 < i1.x0);
+ }
+};
+
+#else // HAVE_STD_SORT
+
static int cmpIntersect(const void *p0, const void *p1) {
- return ((SplashIntersect *)p0)->x0 - ((SplashIntersect *)p1)->x0;
+ SplashIntersect *i0 = (SplashIntersect *)p0;
+ SplashIntersect *i1 = (SplashIntersect *)p1;
+ int cmp;
+
+ if ((cmp = i0->y - i1->y) == 0) {
+ cmp = i0->x0 - i1->x0;
+ }
+ return cmp;
}
+#endif // HAVE_STD_SORT
+
//------------------------------------------------------------------------
// SplashXPathScanner
//------------------------------------------------------------------------
-SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA) {
+SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
+ int clipYMin, int clipYMax) {
SplashXPathSeg *seg;
SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP;
int i;
xPath = xPathA;
eo = eoA;
+ partialClip = gFalse;
// compute the bbox
if (xPath->length == 0) {
@@ -87,16 +112,25 @@ SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA) {
xMax = splashFloor(xMaxFP);
yMin = splashFloor(yMinFP);
yMax = splashFloor(yMaxFP);
+ if (clipYMin > yMin) {
+ yMin = clipYMin;
+ partialClip = gTrue;
+ }
+ if (clipYMax < yMax) {
+ yMax = clipYMax;
+ partialClip = gTrue;
+ }
}
- interY = yMin - 1;
- xPathIdx = 0;
+ allInter = NULL;
inter = NULL;
- interLen = interSize = 0;
+ computeIntersections();
+ interY = yMin - 1;
}
SplashXPathScanner::~SplashXPathScanner() {
gfree(inter);
+ gfree(allInter);
}
void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
@@ -108,12 +142,23 @@ void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
}
void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
- if (interY != y) {
- computeIntersections(y);
+ int interBegin, interEnd, xx, i;
+
+ if (y < yMin || y > yMax) {
+ interBegin = interEnd = 0;
+ } else {
+ interBegin = inter[y - yMin];
+ interEnd = inter[y - yMin + 1];
}
- if (interLen > 0) {
- *spanXMin = inter[0].x0;
- *spanXMax = inter[interLen - 1].x1;
+ if (interBegin < interEnd) {
+ *spanXMin = allInter[interBegin].x0;
+ xx = allInter[interBegin].x1;
+ for (i = interBegin + 1; i < interEnd; ++i) {
+ if (allInter[i].x1 > xx) {
+ xx = allInter[i].x1;
+ }
+ }
+ *spanXMax = xx;
} else {
*spanXMin = xMax + 1;
*spanXMax = xMax;
@@ -121,47 +166,50 @@ void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
}
GBool SplashXPathScanner::test(int x, int y) {
- int count, i;
+ int interBegin, interEnd, count, i;
- if (interY != y) {
- computeIntersections(y);
+ if (y < yMin || y > yMax) {
+ return gFalse;
}
+ interBegin = inter[y - yMin];
+ interEnd = inter[y - yMin + 1];
count = 0;
- for (i = 0; i < interLen && inter[i].x0 <= x; ++i) {
- if (x <= inter[i].x1) {
+ for (i = interBegin; i < interEnd && allInter[i].x0 <= x; ++i) {
+ if (x <= allInter[i].x1) {
return gTrue;
}
- count += inter[i].count;
+ count += allInter[i].count;
}
return eo ? (count & 1) : (count != 0);
}
GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
- int count, xx1, i;
+ int interBegin, interEnd, count, xx1, i;
- if (interY != y) {
- computeIntersections(y);
+ if (y < yMin || y > yMax) {
+ return gFalse;
}
-
+ interBegin = inter[y - yMin];
+ interEnd = inter[y - yMin + 1];
count = 0;
- for (i = 0; i < interLen && inter[i].x1 < x0; ++i) {
- count += inter[i].count;
+ for (i = interBegin; i < interEnd && allInter[i].x1 < x0; ++i) {
+ count += allInter[i].count;
}
// invariant: the subspan [x0,xx1] is inside the path
xx1 = x0 - 1;
while (xx1 < x1) {
- if (i >= interLen) {
+ if (i >= interEnd) {
return gFalse;
}
- if (inter[i].x0 > xx1 + 1 &&
+ if (allInter[i].x0 > xx1 + 1 &&
!(eo ? (count & 1) : (count != 0))) {
return gFalse;
}
- if (inter[i].x1 > xx1) {
- xx1 = inter[i].x1;
+ if (allInter[i].x1 > xx1) {
+ xx1 = allInter[i].x1;
}
- count += inter[i].count;
+ count += allInter[i].count;
++i;
}
@@ -169,25 +217,31 @@ GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
}
GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
- int xx0, xx1;
+ int interEnd, xx0, xx1;
+ if (y < yMin || y > yMax) {
+ return gFalse;
+ }
if (interY != y) {
- computeIntersections(y);
+ interY = y;
+ interIdx = inter[y - yMin];
+ interCount = 0;
}
- if (interIdx >= interLen) {
+ interEnd = inter[y - yMin + 1];
+ if (interIdx >= interEnd) {
return gFalse;
}
- xx0 = inter[interIdx].x0;
- xx1 = inter[interIdx].x1;
- interCount += inter[interIdx].count;
+ xx0 = allInter[interIdx].x0;
+ xx1 = allInter[interIdx].x1;
+ interCount += allInter[interIdx].count;
++interIdx;
- while (interIdx < interLen &&
- (inter[interIdx].x0 <= xx1 ||
+ while (interIdx < interEnd &&
+ (allInter[interIdx].x0 <= xx1 ||
(eo ? (interCount & 1) : (interCount != 0)))) {
- if (inter[interIdx].x1 > xx1) {
- xx1 = inter[interIdx].x1;
+ if (allInter[interIdx].x1 > xx1) {
+ xx1 = allInter[interIdx].x1;
}
- interCount += inter[interIdx].count;
+ interCount += allInter[interIdx].count;
++interIdx;
}
*x0 = xx0;
@@ -195,161 +249,203 @@ GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
return gTrue;
}
-void SplashXPathScanner::computeIntersections(int y) {
- SplashCoord xSegMin, xSegMax, ySegMin, ySegMax, xx0, xx1;
+void SplashXPathScanner::computeIntersections() {
SplashXPathSeg *seg;
- int i, j;
+ SplashCoord segXMin, segXMax, segYMin, segYMax, xx0, xx1;
+ int x, y, y0, y1, i;
- // find the first segment that intersects [y, y+1)
- i = (y >= interY) ? xPathIdx : 0;
- while (i < xPath->length &&
- xPath->segs[i].y0 < y && xPath->segs[i].y1 < y) {
- ++i;
+ if (yMin > yMax) {
+ return;
}
- xPathIdx = i;
- // find all of the segments that intersect [y, y+1) and create an
- // Intersect element for each one
- interLen = 0;
- for (j = i; j < xPath->length; ++j) {
- seg = &xPath->segs[j];
+ // build the list of all intersections
+ allInterLen = 0;
+ allInterSize = 16;
+ allInter = (SplashIntersect *)gmallocn(allInterSize,
+ sizeof(SplashIntersect));
+ for (i = 0; i < xPath->length; ++i) {
+ seg = &xPath->segs[i];
if (seg->flags & splashXPathFlip) {
- ySegMin = seg->y1;
- ySegMax = seg->y0;
+ segYMin = seg->y1;
+ segYMax = seg->y0;
} else {
- ySegMin = seg->y0;
- ySegMax = seg->y1;
- }
-
- // ensure that: ySegMin < y+1
- // y <= ySegMax
- if (ySegMin >= y + 1) {
- break;
- }
- if (ySegMax < y) {
- continue;
- }
-
- if (interLen == interSize) {
- if (interSize == 0) {
- interSize = 16;
- } else {
- interSize *= 2;
- }
- inter = (SplashIntersect *)greallocn(inter, interSize,
- sizeof(SplashIntersect));
+ segYMin = seg->y0;
+ segYMax = seg->y1;
}
-
if (seg->flags & splashXPathHoriz) {
- xx0 = seg->x0;
- xx1 = seg->x1;
+ y = splashFloor(seg->y0);
+ if (y >= yMin && y <= yMax) {
+ addIntersection(segYMin, segYMax, seg->flags,
+ y, splashFloor(seg->x0), splashFloor(seg->x1));
+ }
} else if (seg->flags & splashXPathVert) {
- xx0 = xx1 = seg->x0;
+ y0 = splashFloor(segYMin);
+ if (y0 < yMin) {
+ y0 = yMin;
+ }
+ y1 = splashFloor(segYMax);
+ if (y1 > yMax) {
+ y1 = yMax;
+ }
+ x = splashFloor(seg->x0);
+ for (y = y0; y <= y1; ++y) {
+ addIntersection(segYMin, segYMax, seg->flags, y, x, x);
+ }
} else {
if (seg->x0 < seg->x1) {
- xSegMin = seg->x0;
- xSegMax = seg->x1;
+ segXMin = seg->x0;
+ segXMax = seg->x1;
} else {
- xSegMin = seg->x1;
- xSegMax = seg->x0;
+ segXMin = seg->x1;
+ segXMax = seg->x0;
}
- // intersection with top edge
- xx0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy;
- // intersection with bottom edge
- xx1 = seg->x0 + ((SplashCoord)y + 1 - seg->y0) * seg->dxdy;
- // the segment may not actually extend to the top and/or bottom edges
- if (xx0 < xSegMin) {
- xx0 = xSegMin;
- } else if (xx0 > xSegMax) {
- xx0 = xSegMax;
+ y0 = splashFloor(segYMin);
+ if (y0 < yMin) {
+ y0 = yMin;
}
- if (xx1 < xSegMin) {
- xx1 = xSegMin;
- } else if (xx1 > xSegMax) {
- xx1 = xSegMax;
+ y1 = splashFloor(segYMax);
+ if (y1 > yMax) {
+ y1 = yMax;
+ }
+ // this loop could just add seg->dxdy to xx1 on each iteration,
+ // but that introduces numerical accuracy problems
+ xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy;
+ for (y = y0; y <= y1; ++y) {
+ xx0 = xx1;
+ xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy;
+ // the segment may not actually extend to the top and/or bottom edges
+ if (xx0 < segXMin) {
+ xx0 = segXMin;
+ } else if (xx0 > segXMax) {
+ xx0 = segXMax;
+ }
+ if (xx1 < segXMin) {
+ xx1 = segXMin;
+ } else if (xx1 > segXMax) {
+ xx1 = segXMax;
+ }
+ addIntersection(segYMin, segYMax, seg->flags, y,
+ splashFloor(xx0), splashFloor(xx1));
}
}
- if (xx0 < xx1) {
- inter[interLen].x0 = splashFloor(xx0);
- inter[interLen].x1 = splashFloor(xx1);
- } else {
- inter[interLen].x0 = splashFloor(xx1);
- inter[interLen].x1 = splashFloor(xx0);
- }
- if (ySegMin <= y &&
- (SplashCoord)y < ySegMax &&
- !(seg->flags & splashXPathHoriz)) {
- inter[interLen].count = eo ? 1
- : (seg->flags & splashXPathFlip) ? 1 : -1;
- } else {
- inter[interLen].count = 0;
- }
- ++interLen;
}
+#if HAVE_STD_SORT
+ std::sort(allInter, allInter + allInterLen, cmpIntersectFunctor());
+#else
+ qsort(allInter, allInterLen, sizeof(SplashIntersect), cmpIntersect);
+#endif
- qsort(inter, interLen, sizeof(SplashIntersect), &cmpIntersect);
+ // build the list of y pointers
+ inter = (int *)gmallocn(yMax - yMin + 2, sizeof(int));
+ i = 0;
+ for (y = yMin; y <= yMax; ++y) {
+ inter[y - yMin] = i;
+ while (i < allInterLen && allInter[i].y <= y) {
+ ++i;
+ }
+ }
+ inter[yMax - yMin + 1] = i;
+}
- interY = y;
- interIdx = 0;
- interCount = 0;
+void SplashXPathScanner::addIntersection(double segYMin, double segYMax,
+ Guint segFlags,
+ int y, int x0, int x1) {
+ if (allInterLen == allInterSize) {
+ allInterSize *= 2;
+ allInter = (SplashIntersect *)greallocn(allInter, allInterSize,
+ sizeof(SplashIntersect));
+ }
+ allInter[allInterLen].y = y;
+ if (x0 < x1) {
+ allInter[allInterLen].x0 = x0;
+ allInter[allInterLen].x1 = x1;
+ } else {
+ allInter[allInterLen].x0 = x1;
+ allInter[allInterLen].x1 = x0;
+ }
+ if (segYMin <= y &&
+ (SplashCoord)y < segYMax &&
+ !(segFlags & splashXPathHoriz)) {
+ allInter[allInterLen].count = eo ? 1
+ : (segFlags & splashXPathFlip) ? 1 : -1;
+ } else {
+ allInter[allInterLen].count = 0;
+ }
+ ++allInterLen;
}
void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y) {
- int xx0, xx1, xx, xxMin, xxMax, yy;
+ int xx0, xx1, xx, xxMin, xxMax, yy, interEnd;
Guchar mask;
SplashColorPtr p;
memset(aaBuf->getDataPtr(), 0, aaBuf->getRowSize() * aaBuf->getHeight());
xxMin = aaBuf->getWidth();
xxMax = -1;
- for (yy = 0; yy < splashAASize; ++yy) {
- computeIntersections(splashAASize * y + yy);
- while (interIdx < interLen) {
- xx0 = inter[interIdx].x0;
- xx1 = inter[interIdx].x1;
- interCount += inter[interIdx].count;
- ++interIdx;
- while (interIdx < interLen &&
- (inter[interIdx].x0 <= xx1 ||
- (eo ? (interCount & 1) : (interCount != 0)))) {
- if (inter[interIdx].x1 > xx1) {
- xx1 = inter[interIdx].x1;
- }
- interCount += inter[interIdx].count;
- ++interIdx;
- }
- if (xx0 < 0) {
- xx0 = 0;
- }
- ++xx1;
- if (xx1 > aaBuf->getWidth()) {
- xx1 = aaBuf->getWidth();
+ if (yMin <= yMax) {
+ if (splashAASize * y < yMin) {
+ interIdx = inter[0];
+ } else if (splashAASize * y > yMax) {
+ interIdx = inter[yMax - yMin + 1];
+ } else {
+ interIdx = inter[splashAASize * y - yMin];
+ }
+ for (yy = 0; yy < splashAASize; ++yy) {
+ if (splashAASize * y + yy < yMin) {
+ interEnd = inter[0];
+ } else if (splashAASize * y + yy > yMax) {
+ interEnd = inter[yMax - yMin + 1];
+ } else {
+ interEnd = inter[splashAASize * y + yy - yMin + 1];
}
- // set [xx0, xx1) to 1
- if (xx0 < xx1) {
- xx = xx0;
- p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
- if (xx & 7) {
- mask = 0xff >> (xx & 7);
- if ((xx & ~7) == (xx1 & ~7)) {
- mask &= (Guchar)(0xff00 >> (xx1 & 7));
+ interCount = 0;
+ while (interIdx < interEnd) {
+ xx0 = allInter[interIdx].x0;
+ xx1 = allInter[interIdx].x1;
+ interCount += allInter[interIdx].count;
+ ++interIdx;
+ while (interIdx < interEnd &&
+ (allInter[interIdx].x0 <= xx1 ||
+ (eo ? (interCount & 1) : (interCount != 0)))) {
+ if (allInter[interIdx].x1 > xx1) {
+ xx1 = allInter[interIdx].x1;
}
- *p++ |= mask;
- xx = (xx & ~7) + 8;
+ interCount += allInter[interIdx].count;
+ ++interIdx;
}
- for (; xx + 7 < xx1; xx += 8) {
- *p++ |= 0xff;
+ if (xx0 < 0) {
+ xx0 = 0;
}
- if (xx < xx1) {
- *p |= (Guchar)(0xff00 >> (xx1 & 7));
+ ++xx1;
+ if (xx1 > aaBuf->getWidth()) {
+ xx1 = aaBuf->getWidth();
+ }
+ // set [xx0, xx1) to 1
+ if (xx0 < xx1) {
+ xx = xx0;
+ p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
+ if (xx & 7) {
+ mask = 0xff >> (xx & 7);
+ if ((xx & ~7) == (xx1 & ~7)) {
+ mask &= (Guchar)(0xff00 >> (xx1 & 7));
+ }
+ *p++ |= mask;
+ xx = (xx & ~7) + 8;
+ }
+ for (; xx + 7 < xx1; xx += 8) {
+ *p++ |= 0xff;
+ }
+ if (xx < xx1) {
+ *p |= (Guchar)(0xff00 >> (xx1 & 7));
+ }
+ }
+ if (xx0 < xxMin) {
+ xxMin = xx0;
+ }
+ if (xx1 > xxMax) {
+ xxMax = xx1;
}
- }
- if (xx0 < xxMin) {
- xxMin = xx0;
- }
- if (xx1 > xxMax) {
- xxMax = xx1;
}
}
}
@@ -359,51 +455,65 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y) {
- int xx0, xx1, xx, yy;
+ int xx0, xx1, xx, yy, interEnd;
Guchar mask;
SplashColorPtr p;
for (yy = 0; yy < splashAASize; ++yy) {
xx = *x0 * splashAASize;
- computeIntersections(splashAASize * y + yy);
- while (interIdx < interLen && xx < (*x1 + 1) * splashAASize) {
- xx0 = inter[interIdx].x0;
- xx1 = inter[interIdx].x1;
- interCount += inter[interIdx].count;
- ++interIdx;
- while (interIdx < interLen &&
- (inter[interIdx].x0 <= xx1 ||
- (eo ? (interCount & 1) : (interCount != 0)))) {
- if (inter[interIdx].x1 > xx1) {
- xx1 = inter[interIdx].x1;
+ if (yMin <= yMax) {
+ if (splashAASize * y + yy < yMin) {
+ interIdx = interEnd = inter[0];
+ } else if (splashAASize * y + yy > yMax) {
+ interIdx = interEnd = inter[yMax - yMin + 1];
+ } else {
+ interIdx = inter[splashAASize * y + yy - yMin];
+ if (splashAASize * y + yy > yMax) {
+ interEnd = inter[yMax - yMin + 1];
+ } else {
+ interEnd = inter[splashAASize * y + yy - yMin + 1];
}
- interCount += inter[interIdx].count;
- ++interIdx;
- }
- if (xx0 > aaBuf->getWidth()) {
- xx0 = aaBuf->getWidth();
}
- // set [xx, xx0) to 0
- if (xx < xx0) {
- p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
- if (xx & 7) {
- mask = (Guchar)(0xff00 >> (xx & 7));
- if ((xx & ~7) == (xx0 & ~7)) {
- mask |= 0xff >> (xx0 & 7);
+ interCount = 0;
+ while (interIdx < interEnd && xx < (*x1 + 1) * splashAASize) {
+ xx0 = allInter[interIdx].x0;
+ xx1 = allInter[interIdx].x1;
+ interCount += allInter[interIdx].count;
+ ++interIdx;
+ while (interIdx < interEnd &&
+ (allInter[interIdx].x0 <= xx1 ||
+ (eo ? (interCount & 1) : (interCount != 0)))) {
+ if (allInter[interIdx].x1 > xx1) {
+ xx1 = allInter[interIdx].x1;
}
- *p++ &= mask;
- xx = (xx & ~7) + 8;
+ interCount += allInter[interIdx].count;
+ ++interIdx;
+ }
+ if (xx0 > aaBuf->getWidth()) {
+ xx0 = aaBuf->getWidth();
}
- for (; xx + 7 <= xx0; xx += 8) {
- *p++ = 0x00;
+ // set [xx, xx0) to 0
+ if (xx < xx0) {
+ p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
+ if (xx & 7) {
+ mask = (Guchar)(0xff00 >> (xx & 7));
+ if ((xx & ~7) == (xx0 & ~7)) {
+ mask |= 0xff >> (xx0 & 7);
+ }
+ *p++ &= mask;
+ xx = (xx & ~7) + 8;
+ }
+ for (; xx + 7 < xx0; xx += 8) {
+ *p++ = 0x00;
+ }
+ if (xx < xx0) {
+ *p &= 0xff >> (xx0 & 7);
+ }
}
- if (xx <= xx0) {
- *p &= 0xff >> (xx0 & 7);
+ if (xx1 >= xx) {
+ xx = xx1 + 1;
}
}
- if (xx1 >= xx) {
- xx = xx1 + 1;
- }
}
xx0 = (*x1 + 1) * splashAASize;
// set [xx, xx0) to 0
@@ -417,10 +527,10 @@ void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
*p++ &= mask;
xx = (xx & ~7) + 8;
}
- for (; xx + 7 <= xx0; xx += 8) {
+ for (; xx + 7 < xx0; xx += 8) {
*p++ = 0x00;
}
- if (xx <= xx0) {
+ if (xx < xx0) {
*p &= 0xff >> (xx0 & 7);
}
}
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
index ab02fcc..5bb3aaf 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -27,7 +27,8 @@ class SplashXPathScanner {
public:
// Create a new SplashXPathScanner object. <xPathA> must be sorted.
- SplashXPathScanner(SplashXPath *xPathA, GBool eoA);
+ SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
+ int clipYMin, int clipYMax);
~SplashXPathScanner();
@@ -38,6 +39,10 @@ public:
// Return the path's bounding box.
void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA);
+ // Returns true if at least part of the path was outside the
+ // clipYMin/clipYMax bounds passed to the constructor.
+ GBool hasPartialClip() { return partialClip; }
+
// Return the min/max x values for the span at <y>.
void getSpanBounds(int y, int *spanXMin, int *spanXMax);
@@ -66,22 +71,25 @@ public:
private:
- void computeIntersections(int y);
+ void computeIntersections();
+ void addIntersection(double segYMin, double segYMax,
+ Guint segFlags,
+ int y, int x0, int x1);
SplashXPath *xPath;
GBool eo;
int xMin, yMin, xMax, yMax;
+ GBool partialClip;
- int interY; // current y value
+ SplashIntersect *allInter; // array of intersections
+ int allInterLen; // number of intersections in <allInter>
+ int allInterSize; // size of the <allInter> array
+ int *inter; // indexes into <allInter> for each y value
+ int interY; // current y value - used by getNextSpan
int interIdx; // current index into <inter> - used by
// getNextSpan
int interCount; // current EO/NZWN counter - used by
// getNextSpan
- int xPathIdx; // current index into <xPath> - used by
- // computeIntersections
- SplashIntersect *inter; // intersections array for <interY>
- int interLen; // number of intersections in <inter>
- int interSize; // size of the <inter> array
};
#endif
diff --git a/xpdf/Annot.cc b/xpdf/Annot.cc
index 1f5d8d1..887157f 100644
--- a/xpdf/Annot.cc
+++ b/xpdf/Annot.cc
@@ -22,6 +22,8 @@
#include "Gfx.h"
#include "GfxFont.h"
#include "Lexer.h"
+#include "PDFDoc.h"
+#include "OptionalContent.h"
#include "Annot.h"
//------------------------------------------------------------------------
@@ -84,7 +86,7 @@ AnnotBorderStyle::~AnnotBorderStyle() {
// Annot
//------------------------------------------------------------------------
-Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA) {
+Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) {
Object apObj, asObj, obj1, obj2, obj3;
AnnotBorderType borderType;
double borderWidth;
@@ -95,9 +97,11 @@ Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA) {
int i;
ok = gTrue;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
ref = *refA;
type = NULL;
+ appearanceState = NULL;
appearBuf = NULL;
borderStyle = NULL;
@@ -136,7 +140,7 @@ Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA) {
t = yMin; yMin = yMax; yMax = t;
}
} else {
- error(-1, "Bad bounding box for annotation");
+ error(errSyntaxError, -1, "Bad bounding box for annotation");
ok = gFalse;
}
obj1.free();
@@ -242,38 +246,54 @@ Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA) {
borderDash, borderDashLength,
borderR, borderG, borderB);
+ //----- get the appearance state
+
+ dict->lookup("AP", &apObj);
+ dict->lookup("AS", &asObj);
+ if (asObj.isName()) {
+ appearanceState = new GString(asObj.getName());
+ } else if (apObj.isDict()) {
+ apObj.dictLookup("N", &obj1);
+ if (obj1.isDict() && obj1.dictGetLength() == 1) {
+ appearanceState = new GString(obj1.dictGetKey(0));
+ }
+ obj1.free();
+ }
+ if (!appearanceState) {
+ appearanceState = new GString("Off");
+ }
+ asObj.free();
+
//----- get the annotation appearance
- if (dict->lookup("AP", &apObj)->isDict()) {
- if (dict->lookup("AS", &asObj)->isName()) {
- if (apObj.dictLookup("N", &obj1)->isDict()) {
- if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
- obj2.copy(&appearance);
- ok = gTrue;
- } else {
- obj2.free();
- if (obj1.dictLookupNF("Off", &obj2)->isRef()) {
- obj2.copy(&appearance);
- }
- }
- obj2.free();
- }
- obj1.free();
- } else {
- if (apObj.dictLookupNF("N", &obj1)->isRef()) {
- obj1.copy(&appearance);
+ if (apObj.isDict()) {
+ apObj.dictLookup("N", &obj1);
+ apObj.dictLookupNF("N", &obj2);
+ if (obj1.isDict()) {
+ if (obj1.dictLookupNF(appearanceState->getCString(), &obj3)->isRef()) {
+ obj3.copy(&appearance);
}
- obj1.free();
+ obj3.free();
+ } else if (obj2.isRef()) {
+ obj2.copy(&appearance);
}
- asObj.free();
+ obj1.free();
+ obj2.free();
}
apObj.free();
+
+ //----- get the optional content entry
+
+ dict->lookupNF("OC", &ocObj);
}
Annot::~Annot() {
if (type) {
delete type;
}
+ if (appearanceState) {
+ delete appearanceState;
+ }
appearance.free();
if (appearBuf) {
delete appearBuf;
@@ -281,6 +301,7 @@ Annot::~Annot() {
if (borderStyle) {
delete borderStyle;
}
+ ocObj.free();
}
void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
@@ -294,10 +315,10 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
GString *caption, *da;
GString **text;
GBool *selection;
- int dashLength, ff, quadding, comb, nOptions, topIdx, i, j;
+ int rot, dashLength, ff, quadding, comb, nOptions, topIdx, i, j;
// must be a Widget annotation
- if (type->cmp("Widget")) {
+ if (type && type->cmp("Widget")) {
return;
}
@@ -322,10 +343,10 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
}
// get the field type
- fieldLookup(field, "FT", &ftObj);
+ fieldLookup(field, acroForm, "FT", &ftObj);
// get the field flags (Ff) value
- if (fieldLookup(field, "Ff", &obj1)->isInt()) {
+ if (fieldLookup(field, acroForm, "Ff", &obj1)->isInt()) {
ff = obj1.getInt();
} else {
ff = 0;
@@ -432,18 +453,18 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
}
// get the resource dictionary
- acroForm->lookup("DR", &drObj);
+ fieldLookup(field, acroForm, "DR", &drObj);
// build the font dictionary
if (drObj.isDict() && drObj.dictLookup("Font", &obj1)->isDict()) {
- fontDict = new GfxFontDict(xref, NULL, obj1.getDict());
+ fontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
} else {
fontDict = NULL;
}
obj1.free();
// get the default appearance string
- if (fieldLookup(field, "DA", &obj1)->isNull()) {
+ if (fieldLookup(field, acroForm, "DA", &obj1)->isNull()) {
obj1.free();
acroForm->lookup("DA", &obj1);
}
@@ -454,6 +475,15 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
}
obj1.free();
+ // get the rotation value
+ rot = 0;
+ if (mkDict) {
+ if (mkDict->lookup("R", &obj1)->isInt()) {
+ rot = obj1.getInt();
+ }
+ obj1.free();
+ }
+
// draw the field contents
if (ftObj.isName("Btn")) {
caption = NULL;
@@ -466,45 +496,41 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
// radio button
if (ff & fieldFlagRadio) {
//~ Acrobat doesn't draw a caption if there is no AP dict (?)
- if (fieldLookup(field, "V", &obj1)->isName()) {
- if (annot->lookup("AS", &obj2)->isName(obj1.getName())) {
- if (caption) {
- drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gTrue);
- } else {
- if (mkDict) {
- if (mkDict->lookup("BC", &obj3)->isArray() &&
- obj3.arrayGetLength() > 0) {
- dx = xMax - xMin;
- dy = yMax - yMin;
- setColor(obj3.getArray(), gTrue, 0);
- drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy),
- gTrue);
- }
- obj3.free();
+ if (fieldLookup(field, acroForm, "V", &obj1)
+ ->isName(appearanceState->getCString())) {
+ if (caption) {
+ drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
+ gFalse, gTrue, rot);
+ } else {
+ if (mkDict) {
+ if (mkDict->lookup("BC", &obj2)->isArray() &&
+ obj2.arrayGetLength() > 0) {
+ dx = xMax - xMin;
+ dy = yMax - yMin;
+ setColor(obj2.getArray(), gTrue, 0);
+ drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy),
+ gTrue);
}
+ obj2.free();
}
}
- obj2.free();
}
obj1.free();
// pushbutton
} else if (ff & fieldFlagPushbutton) {
if (caption) {
drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gFalse);
+ gFalse, gFalse, rot);
}
// checkbox
} else {
- // According to the PDF spec the off state must be named "Off",
- // and the on state can be named anything, but Acrobat apparently
- // looks for "Yes" and treats anything else as off.
- if (fieldLookup(field, "V", &obj1)->isName("Yes")) {
+ fieldLookup(field, acroForm, "V", &obj1);
+ if (obj1.isName() && !obj1.isName("Off")) {
if (!caption) {
caption = new GString("3"); // ZapfDingbats checkmark
}
drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gTrue);
+ gFalse, gTrue, rot);
}
obj1.free();
}
@@ -513,8 +539,12 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
}
} else if (ftObj.isName("Tx")) {
//~ value strings can be Unicode
- if (fieldLookup(field, "V", &obj1)->isString()) {
- if (fieldLookup(field, "Q", &obj2)->isInt()) {
+ if (!fieldLookup(field, acroForm, "V", &obj1)->isString()) {
+ obj1.free();
+ fieldLookup(field, acroForm, "DV", &obj1);
+ }
+ if (obj1.isString()) {
+ if (fieldLookup(field, acroForm, "Q", &obj2)->isInt()) {
quadding = obj2.getInt();
} else {
quadding = fieldQuadLeft;
@@ -522,18 +552,18 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
obj2.free();
comb = 0;
if (ff & fieldFlagComb) {
- if (fieldLookup(field, "MaxLen", &obj2)->isInt()) {
+ if (fieldLookup(field, acroForm, "MaxLen", &obj2)->isInt()) {
comb = obj2.getInt();
}
obj2.free();
}
drawText(obj1.getString(), da, fontDict,
- ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse);
+ ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse, rot);
}
obj1.free();
} else if (ftObj.isName("Ch")) {
//~ value/option strings can be Unicode
- if (fieldLookup(field, "Q", &obj1)->isInt()) {
+ if (fieldLookup(field, acroForm, "Q", &obj1)->isInt()) {
quadding = obj1.getInt();
} else {
quadding = fieldQuadLeft;
@@ -541,9 +571,9 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
obj1.free();
// combo box
if (ff & fieldFlagCombo) {
- if (fieldLookup(field, "V", &obj1)->isString()) {
+ if (fieldLookup(field, acroForm, "V", &obj1)->isString()) {
drawText(obj1.getString(), da, fontDict,
- gFalse, 0, quadding, gTrue, gFalse);
+ gFalse, 0, quadding, gTrue, gFalse, rot);
//~ Acrobat draws a popup icon on the right side
}
obj1.free();
@@ -572,7 +602,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
// get the selected option(s)
selection = (GBool *)gmallocn(nOptions, sizeof(GBool));
//~ need to use the I field in addition to the V field
- fieldLookup(field, "V", &obj2);
+ fieldLookup(field, acroForm, "V", &obj2);
for (i = 0; i < nOptions; ++i) {
selection[i] = gFalse;
if (obj2.isString()) {
@@ -610,7 +640,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
} else if (ftObj.isName("Sig")) {
//~unimp
} else {
- error(-1, "Unknown field type");
+ error(errSyntaxError, -1, "Unknown field type");
}
if (da) {
@@ -618,11 +648,11 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
}
// build the appearance stream dictionary
- appearDict.initDict(xref);
+ appearDict.initDict(doc->getXRef());
appearDict.dictAdd(copyString("Length"),
obj1.initInt(appearBuf->getLength()));
appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form"));
- obj1.initArray(xref);
+ obj1.initArray(doc->getXRef());
obj1.arrayAdd(obj2.initReal(0));
obj1.arrayAdd(obj2.initReal(0));
obj1.arrayAdd(obj2.initReal(xMax - xMin));
@@ -699,10 +729,12 @@ void Annot::setColor(Array *a, GBool fill, int adjust) {
// Draw the variable text or caption for a field.
void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
GBool multiline, int comb, int quadding,
- GBool txField, GBool forceZapfDingbats) {
+ GBool txField, GBool forceZapfDingbats, int rot) {
+ GString *text2;
GList *daToks;
GString *tok;
GfxFont *font;
+ double dx, dy;
double fontSize, fontSize2, border, x, xPrev, y, w, w2, wMax;
int tfPos, tmPos, i, j, k, c;
@@ -710,6 +742,23 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
//~ and only replace the marked content portion of it
//~ (this is only relevant for Tx fields)
+ // check for a Unicode string
+ //~ this currently drops all non-Latin1 characters
+ if (text->getLength() >= 2 &&
+ text->getChar(0) == '\xfe' && text->getChar(1) == '\xff') {
+ text2 = new GString();
+ for (i = 2; i+1 < text->getLength(); i += 2) {
+ c = ((text->getChar(i) & 0xff) << 8) + (text->getChar(i+1) & 0xff);
+ if (c <= 0xff) {
+ text2->append((char)c);
+ } else {
+ text2->append('?');
+ }
+ }
+ } else {
+ text2 = text;
+ }
+
// parse the default appearance string
tfPos = tmPos = -1;
if (da) {
@@ -757,15 +806,16 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
tok = (GString *)daToks->get(tfPos);
if (tok->getLength() >= 1 && tok->getChar(0) == '/') {
if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) {
- error(-1, "Unknown font in field's DA string");
+ error(errSyntaxError, -1, "Unknown font in field's DA string");
}
} else {
- error(-1, "Invalid font name in 'Tf' operator in field's DA string");
+ error(errSyntaxError, -1,
+ "Invalid font name in 'Tf' operator in field's DA string");
}
tok = (GString *)daToks->get(tfPos + 1);
fontSize = atof(tok->getCString());
} else {
- error(-1, "Missing 'Tf' operator in field's DA string");
+ error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string");
}
// get the border width
@@ -776,22 +826,39 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
appearBuf->append("/Tx BMC\n");
}
appearBuf->append("q\n");
+ if (rot == 90) {
+ appearBuf->appendf("0 1 -1 0 {0:.2f} 0 cm\n", xMax - xMin);
+ dx = yMax - yMin;
+ dy = xMax - xMin;
+ } else if (rot == 180) {
+ appearBuf->appendf("-1 0 0 -1 {0:.2f} {1:.2f} cm\n",
+ xMax - xMin, yMax - yMin);
+ dx = xMax - yMax;
+ dy = yMax - yMin;
+ } else if (rot == 270) {
+ appearBuf->appendf("0 -1 1 0 0 {0:.2f} cm\n", yMax - yMin);
+ dx = yMax - yMin;
+ dy = xMax - xMin;
+ } else { // assume rot == 0
+ dx = xMax - xMin;
+ dy = yMax - yMin;
+ }
appearBuf->append("BT\n");
// multi-line text
if (multiline) {
// note: the comb flag is ignored in multiline mode
- wMax = xMax - xMin - 2 * border - 4;
+ wMax = dx - 2 * border - 4;
// compute font autosize
if (fontSize == 0) {
for (fontSize = 20; fontSize > 1; --fontSize) {
- y = yMax - yMin;
+ y = dy - 3;
w2 = 0;
i = 0;
- while (i < text->getLength()) {
- getNextLine(text, i, font, fontSize, wMax, &j, &w, &k);
+ while (i < text2->getLength()) {
+ getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k);
if (w > w2) {
w2 = w;
}
@@ -813,7 +880,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// starting y coordinate
// (note: each line of text starts with a Td operator that moves
// down a line)
- y = yMax - yMin;
+ y = dy - 3;
// set the font matrix
if (tmPos >= 0) {
@@ -840,9 +907,9 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// write a series of lines of text
i = 0;
xPrev = 0;
- while (i < text->getLength()) {
+ while (i < text2->getLength()) {
- getNextLine(text, i, font, fontSize, wMax, &j, &w, &k);
+ getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k);
// compute text start position
switch (quadding) {
@@ -851,10 +918,10 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
x = border + 2;
break;
case fieldQuadCenter:
- x = (xMax - xMin - w) / 2;
+ x = (dx - w) / 2;
break;
case fieldQuadRight:
- x = xMax - xMin - border - 2 - w;
+ x = dx - border - 2 - w;
break;
}
@@ -862,7 +929,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
appearBuf->appendf("{0:.2f} {1:.2f} Td\n", x - xPrev, -fontSize);
appearBuf->append('(');
for (; i < j; ++i) {
- c = text->getChar(i) & 0xff;
+ c = text2->getChar(i) & 0xff;
if (c == '(' || c == ')' || c == '\\') {
appearBuf->append('\\');
appearBuf->append(c);
@@ -887,11 +954,11 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
if (comb > 0) {
// compute comb spacing
- w = (xMax - xMin - 2 * border) / comb;
+ w = (dx - 2 * border) / comb;
// compute font autosize
if (fontSize == 0) {
- fontSize = yMax - yMin - 2 * border;
+ fontSize = dy - 2 * border;
if (w < fontSize) {
fontSize = w;
}
@@ -910,13 +977,13 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
x = border + 2;
break;
case fieldQuadCenter:
- x = border + 2 + 0.5 * (comb - text->getLength()) * w;
+ x = border + 2 + 0.5 * (comb - text2->getLength()) * w;
break;
case fieldQuadRight:
- x = border + 2 + (comb - text->getLength()) * w;
+ x = border + 2 + (comb - text2->getLength()) * w;
break;
}
- y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
+ y = 0.5 * dy - 0.4 * fontSize;
// set the font matrix
if (tmPos >= 0) {
@@ -943,12 +1010,12 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// write the text string
//~ this should center (instead of left-justify) each character within
//~ its comb cell
- for (i = 0; i < text->getLength(); ++i) {
+ for (i = 0; i < text2->getLength(); ++i) {
if (i > 0) {
appearBuf->appendf("{0:.2f} 0 Td\n", w);
}
appearBuf->append('(');
- c = text->getChar(i) & 0xff;
+ c = text2->getChar(i) & 0xff;
if (c == '(' || c == ')' || c == '\\') {
appearBuf->append('\\');
appearBuf->append(c);
@@ -966,18 +1033,18 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// compute string width
if (font && !font->isCIDFont()) {
w = 0;
- for (i = 0; i < text->getLength(); ++i) {
- w += ((Gfx8BitFont *)font)->getWidth(text->getChar(i));
+ for (i = 0; i < text2->getLength(); ++i) {
+ w += ((Gfx8BitFont *)font)->getWidth(text2->getChar(i));
}
} else {
// otherwise, make a crude estimate
- w = text->getLength() * 0.5;
+ w = text2->getLength() * 0.5;
}
// compute font autosize
if (fontSize == 0) {
- fontSize = yMax - yMin - 2 * border;
- fontSize2 = (xMax - xMin - 4 - 2 * border) / w;
+ fontSize = dy - 2 * border;
+ fontSize2 = (dx - 4 - 2 * border) / w;
if (fontSize2 < fontSize) {
fontSize = fontSize2;
}
@@ -997,13 +1064,13 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
x = border + 2;
break;
case fieldQuadCenter:
- x = (xMax - xMin - w) / 2;
+ x = (dx - w) / 2;
break;
case fieldQuadRight:
- x = xMax - xMin - border - 2 - w;
+ x = dx - border - 2 - w;
break;
}
- y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
+ y = 0.5 * dy - 0.4 * fontSize;
// set the font matrix
if (tmPos >= 0) {
@@ -1029,8 +1096,8 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// write the text string
appearBuf->append('(');
- for (i = 0; i < text->getLength(); ++i) {
- c = text->getChar(i) & 0xff;
+ for (i = 0; i < text2->getLength(); ++i) {
+ c = text2->getChar(i) & 0xff;
if (c == '(' || c == ')' || c == '\\') {
appearBuf->append('\\');
appearBuf->append(c);
@@ -1054,6 +1121,9 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
if (daToks) {
deleteGList(daToks, GString);
}
+ if (text2 != text) {
+ delete text2;
+ }
}
// Draw the variable text or caption for a field.
@@ -1105,15 +1175,16 @@ void Annot::drawListBox(GString **text, GBool *selection,
tok = (GString *)daToks->get(tfPos);
if (tok->getLength() >= 1 && tok->getChar(0) == '/') {
if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) {
- error(-1, "Unknown font in field's DA string");
+ error(errSyntaxError, -1, "Unknown font in field's DA string");
}
} else {
- error(-1, "Invalid font name in 'Tf' operator in field's DA string");
+ error(errSyntaxError, -1,
+ "Invalid font name in 'Tf' operator in field's DA string");
}
tok = (GString *)daToks->get(tfPos + 1);
fontSize = atof(tok->getCString());
} else {
- error(-1, "Missing 'Tf' operator in field's DA string");
+ error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string");
}
// get the border width
@@ -1391,7 +1462,8 @@ void Annot::drawCircleBottomRight(double cx, double cy, double r) {
}
// Look up an inheritable field dictionary entry.
-Object *Annot::fieldLookup(Dict *field, char *key, Object *obj) {
+Object *Annot::fieldLookup(Dict *field, Dict *acroForm,
+ const char *key, Object *obj) {
Dict *dict;
Object parent;
@@ -1401,7 +1473,11 @@ Object *Annot::fieldLookup(Dict *field, char *key, Object *obj) {
}
obj->free();
if (dict->lookup("Parent", &parent)->isDict()) {
- fieldLookup(parent.getDict(), key, obj);
+ fieldLookup(parent.getDict(), acroForm, key, obj);
+ } else if (acroForm) {
+ // some fields don't specify a parent, so we check the AcroForm
+ // dictionary just in case
+ fieldLookup(acroForm, NULL, key, obj);
} else {
obj->initNull();
}
@@ -1411,7 +1487,7 @@ Object *Annot::fieldLookup(Dict *field, char *key, Object *obj) {
void Annot::draw(Gfx *gfx, GBool printing) {
Object obj;
- GBool isLink;
+ GBool oc, isLink;
// check the flags
if ((flags & annotFlagHidden) ||
@@ -1420,32 +1496,44 @@ void Annot::draw(Gfx *gfx, GBool printing) {
return;
}
+ // check the optional content entry
+ if (doc->getOptionalContent()->evalOCObject(&ocObj, &oc) && !oc) {
+ return;
+ }
+
// draw the appearance stream
isLink = type && !type->cmp("Link");
- appearance.fetch(xref, &obj);
+ appearance.fetch(doc->getXRef(), &obj);
gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL,
xMin, yMin, xMax, yMax);
obj.free();
}
+Object *Annot::getObject(Object *obj) {
+ if (ref.num >= 0) {
+ xref->fetch(ref.num, ref.gen, obj);
+ } else {
+ obj->initNull();
+ }
+ return obj;
+}
+
//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
-Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
- Dict *acroForm;
+Annots::Annots(PDFDoc *docA, Object *annotsObj) {
Annot *annot;
Object obj1;
Ref ref;
int size;
int i;
+ doc = docA;
annots = NULL;
size = 0;
nAnnots = 0;
- acroForm = catalog->getAcroForm()->isDict() ?
- catalog->getAcroForm()->getDict() : NULL;
if (annotsObj->isArray()) {
for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
if (annotsObj->arrayGetNF(i, &obj1)->isRef()) {
@@ -1456,7 +1544,7 @@ Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
ref.num = ref.gen = -1;
}
if (obj1.isDict()) {
- annot = new Annot(xref, acroForm, obj1.getDict(), &ref);
+ annot = new Annot(doc, obj1.getDict(), &ref);
if (annot->isOk()) {
if (nAnnots >= size) {
size += 16;
@@ -1481,11 +1569,14 @@ Annots::~Annots() {
gfree(annots);
}
-void Annots::generateAppearances(Dict *acroForm) {
+void Annots::generateAppearances() {
+ Dict *acroForm;
Object obj1, obj2;
Ref ref;
int i;
+ acroForm = doc->getCatalog()->getAcroForm()->isDict() ?
+ doc->getCatalog()->getAcroForm()->getDict() : NULL;
if (acroForm->lookup("Fields", &obj1)->isArray()) {
for (i = 0; i < obj1.arrayGetLength(); ++i) {
if (obj1.arrayGetNF(i, &obj2)->isRef()) {
diff --git a/xpdf/Annot.h b/xpdf/Annot.h
index 1f89d49..987e80e 100644
--- a/xpdf/Annot.h
+++ b/xpdf/Annot.h
@@ -19,6 +19,7 @@ class XRef;
class Catalog;
class Gfx;
class GfxFontDict;
+class PDFDoc;
//------------------------------------------------------------------------
// AnnotBorderStyle
@@ -63,12 +64,19 @@ private:
class Annot {
public:
- Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA);
+ Annot(PDFDoc *docA, Dict *dict, Ref *refA);
~Annot();
GBool isOk() { return ok; }
void draw(Gfx *gfx, GBool printing);
+ GString *getType() { return type; }
+ double getXMin() { return xMin; }
+ double getYMin() { return yMin; }
+ double getXMax() { return xMax; }
+ double getYMax() { return yMax; }
+ Object *getObject(Object *obj);
+
// Get appearance object.
Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
@@ -84,7 +92,7 @@ private:
void setColor(Array *a, GBool fill, int adjust);
void drawText(GString *text, GString *da, GfxFontDict *fontDict,
GBool multiline, int comb, int quadding,
- GBool txField, GBool forceZapfDingbats);
+ GBool txField, GBool forceZapfDingbats, int rot);
void drawListBox(GString **text, GBool *selection,
int nOptions, int topIdx,
GString *da, GfxFontDict *fontDict, GBool quadding);
@@ -94,11 +102,14 @@ private:
void drawCircle(double cx, double cy, double r, GBool fill);
void drawCircleTopLeft(double cx, double cy, double r);
void drawCircleBottomRight(double cx, double cy, double r);
- Object *fieldLookup(Dict *field, char *key, Object *obj);
+ Object *fieldLookup(Dict *field, Dict *acroForm,
+ const char *key, Object *obj);
+ PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
Ref ref; // object ref identifying this annotation
GString *type; // annotation type
+ GString *appearanceState; // appearance state name
Object appearance; // a reference to the Form XObject stream
// for the normal appearance
GString *appearBuf;
@@ -106,6 +117,7 @@ private:
xMax, yMax;
Guint flags;
AnnotBorderStyle *borderStyle;
+ Object ocObj; // optional content entry
GBool ok;
};
@@ -117,7 +129,7 @@ class Annots {
public:
// Build a list of Annot objects.
- Annots(XRef *xref, Catalog *catalog, Object *annotsObj);
+ Annots(PDFDoc *docA, Object *annotsObj);
~Annots();
@@ -127,7 +139,7 @@ public:
// (Re)generate the appearance streams for all annotations belonging
// to a form field.
- void generateAppearances(Dict *acroForm);
+ void generateAppearances();
private:
@@ -135,6 +147,7 @@ private:
Dict *acroForm);
Annot *findAnnot(Ref *ref);
+ PDFDoc *doc;
Annot **annots;
int nAnnots;
};
diff --git a/xpdf/BuiltinFont.cc b/xpdf/BuiltinFont.cc
index ce98957..33c9fa5 100644
--- a/xpdf/BuiltinFont.cc
+++ b/xpdf/BuiltinFont.cc
@@ -39,7 +39,7 @@ BuiltinFontWidths::~BuiltinFontWidths() {
gfree(tab);
}
-GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) {
+GBool BuiltinFontWidths::getWidth(const char *name, Gushort *width) {
int h;
BuiltinFontWidth *p;
@@ -53,8 +53,8 @@ GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) {
return gFalse;
}
-int BuiltinFontWidths::hash(char *name) {
- char *p;
+int BuiltinFontWidths::hash(const char *name) {
+ const char *p;
unsigned int h;
h = 0;
diff --git a/xpdf/BuiltinFont.h b/xpdf/BuiltinFont.h
index 903ed19..9cddb0c 100644
--- a/xpdf/BuiltinFont.h
+++ b/xpdf/BuiltinFont.h
@@ -23,8 +23,8 @@ class BuiltinFontWidths;
//------------------------------------------------------------------------
struct BuiltinFont {
- char *name;
- char **defaultBaseEnc;
+ const char *name;
+ const char **defaultBaseEnc;
short ascent;
short descent;
short bbox[4];
@@ -34,7 +34,7 @@ struct BuiltinFont {
//------------------------------------------------------------------------
struct BuiltinFontWidth {
- char *name;
+ const char *name;
Gushort width;
BuiltinFontWidth *next;
};
@@ -44,11 +44,11 @@ public:
BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA);
~BuiltinFontWidths();
- GBool getWidth(char *name, Gushort *width);
+ GBool getWidth(const char *name, Gushort *width);
private:
- int hash(char *name);
+ int hash(const char *name);
BuiltinFontWidth **tab;
int size;
diff --git a/xpdf/CMap.cc b/xpdf/CMap.cc
index 303cf09..bb80bdd 100644
--- a/xpdf/CMap.cc
+++ b/xpdf/CMap.cc
@@ -22,6 +22,8 @@
#include "Error.h"
#include "GlobalParams.h"
#include "PSTokenizer.h"
+#include "Object.h"
+#include "Stream.h"
#include "CMap.h"
//------------------------------------------------------------------------
@@ -40,16 +42,39 @@ static int getCharFromFile(void *data) {
return fgetc((FILE *)data);
}
+static int getCharFromStream(void *data) {
+ return ((Stream *)data)->getChar();
+}
+
//------------------------------------------------------------------------
+CMap *CMap::parse(CMapCache *cache, GString *collectionA, Object *obj) {
+ CMap *cMap;
+ GString *cMapNameA;
+
+ if (obj->isName()) {
+ cMapNameA = new GString(obj->getName());
+ if (!(cMap = globalParams->getCMap(collectionA, cMapNameA))) {
+ error(errSyntaxError, -1,
+ "Unknown CMap '{0:t}' for character collection '{1:t}'",
+ cMapNameA, collectionA);
+ }
+ delete cMapNameA;
+ } else if (obj->isStream()) {
+ if (!(cMap = CMap::parse(NULL, collectionA, obj->getStream()))) {
+ error(errSyntaxError, -1, "Invalid CMap in Type 0 font");
+ }
+ } else {
+ error(errSyntaxError, -1, "Invalid Encoding in Type 0 font");
+ return NULL;
+ }
+ return cMap;
+}
+
CMap *CMap::parse(CMapCache *cache, GString *collectionA,
GString *cMapNameA) {
FILE *f;
- CMap *cmap;
- PSTokenizer *pst;
- char tok1[256], tok2[256], tok3[256];
- int n1, n2, n3;
- Guint start, end, code;
+ CMap *cMap;
if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
@@ -61,43 +86,53 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA,
return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
}
- error(-1, "Couldn't find '%s' CMap file for '%s' collection",
- cMapNameA->getCString(), collectionA->getCString());
+ error(errSyntaxError, -1,
+ "Couldn't find '{0:t}' CMap file for '{1:t}' collection",
+ cMapNameA, collectionA);
return NULL;
}
- cmap = new CMap(collectionA->copy(), cMapNameA->copy());
+ cMap = new CMap(collectionA->copy(), cMapNameA->copy());
+ cMap->parse2(cache, &getCharFromFile, f);
+
+ fclose(f);
+
+ return cMap;
+}
+
+CMap *CMap::parse(CMapCache *cache, GString *collectionA, Stream *str) {
+ Object obj1;
+ CMap *cMap;
+
+ cMap = new CMap(collectionA->copy(), NULL);
+
+ if (!str->getDict()->lookup("UseCMap", &obj1)->isNull()) {
+ cMap->useCMap(cache, &obj1);
+ }
+ obj1.free();
+
+ str->reset();
+ cMap->parse2(cache, &getCharFromStream, str);
+ str->close();
+ return cMap;
+}
+
+void CMap::parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data) {
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
+ int n1, n2, n3;
+ Guint start, end, code;
- pst = new PSTokenizer(&getCharFromFile, f);
+ pst = new PSTokenizer(getCharFunc, data);
pst->getToken(tok1, sizeof(tok1), &n1);
while (pst->getToken(tok2, sizeof(tok2), &n2)) {
if (!strcmp(tok2, "usecmap")) {
if (tok1[0] == '/') {
- cmap->useCMap(cache, tok1 + 1);
+ useCMap(cache, tok1 + 1);
}
pst->getToken(tok1, sizeof(tok1), &n1);
} else if (!strcmp(tok1, "/WMode")) {
- cmap->wMode = atoi(tok2);
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "begincodespacerange")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endcodespacerange")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endcodespacerange")) {
- error(-1, "Illegal entry in codespacerange block in CMap");
- break;
- }
- if (tok1[0] == '<' && tok2[0] == '<' &&
- n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
- tok1[n1 - 1] = tok2[n1 - 1] = '\0';
- sscanf(tok1 + 1, "%x", &start);
- sscanf(tok2 + 1, "%x", &end);
- n1 = (n1 - 2) / 2;
- cmap->addCodeSpace(cmap->vector, start, end, n1);
- }
- }
+ wMode = atoi(tok2);
pst->getToken(tok1, sizeof(tok1), &n1);
} else if (!strcmp(tok2, "begincidchar")) {
while (pst->getToken(tok1, sizeof(tok1), &n1)) {
@@ -106,21 +141,21 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA,
}
if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
!strcmp(tok2, "endcidchar")) {
- error(-1, "Illegal entry in cidchar block in CMap");
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
break;
}
if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
n1 >= 4 && (n1 & 1) == 0)) {
- error(-1, "Illegal entry in cidchar block in CMap");
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
continue;
}
tok1[n1 - 1] = '\0';
if (sscanf(tok1 + 1, "%x", &code) != 1) {
- error(-1, "Illegal entry in cidchar block in CMap");
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
continue;
}
n1 = (n1 - 2) / 2;
- cmap->addCIDs(code, code, n1, (CID)atoi(tok2));
+ addCIDs(code, code, n1, (CID)atoi(tok2));
}
pst->getToken(tok1, sizeof(tok1), &n1);
} else if (!strcmp(tok2, "begincidrange")) {
@@ -132,7 +167,7 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA,
!strcmp(tok2, "endcidrange") ||
!pst->getToken(tok3, sizeof(tok3), &n3) ||
!strcmp(tok3, "endcidrange")) {
- error(-1, "Illegal entry in cidrange block in CMap");
+ error(errSyntaxError, -1, "Illegal entry in cidrange block in CMap");
break;
}
if (tok1[0] == '<' && tok2[0] == '<' &&
@@ -141,7 +176,7 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA,
sscanf(tok1 + 1, "%x", &start);
sscanf(tok2 + 1, "%x", &end);
n1 = (n1 - 2) / 2;
- cmap->addCIDs(start, end, n1, (CID)atoi(tok3));
+ addCIDs(start, end, n1, (CID)atoi(tok3));
}
}
pst->getToken(tok1, sizeof(tok1), &n1);
@@ -150,10 +185,6 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA,
}
}
delete pst;
-
- fclose(f);
-
- return cmap;
}
CMap::CMap(GString *collectionA, GString *cMapNameA) {
@@ -161,6 +192,7 @@ CMap::CMap(GString *collectionA, GString *cMapNameA) {
collection = collectionA;
cMapName = cMapNameA;
+ isIdent = gFalse;
wMode = 0;
vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
for (i = 0; i < 256; ++i) {
@@ -176,6 +208,7 @@ CMap::CMap(GString *collectionA, GString *cMapNameA) {
CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
collection = collectionA;
cMapName = cMapNameA;
+ isIdent = gTrue;
wMode = wModeA;
vector = NULL;
refCnt = 1;
@@ -189,12 +222,37 @@ void CMap::useCMap(CMapCache *cache, char *useName) {
CMap *subCMap;
useNameStr = new GString(useName);
- subCMap = cache->getCMap(collection, useNameStr);
+ // if cache is non-NULL, we already have a lock, and we can use
+ // CMapCache::getCMap() directly; otherwise, we need to use
+ // GlobalParams::getCMap() in order to acqure the lock need to use
+ // GlobalParams::getCMap
+ if (cache) {
+ subCMap = cache->getCMap(collection, useNameStr);
+ } else {
+ subCMap = globalParams->getCMap(collection, useNameStr);
+ }
delete useNameStr;
if (!subCMap) {
return;
}
- copyVector(vector, subCMap->vector);
+ isIdent = subCMap->isIdent;
+ if (subCMap->vector) {
+ copyVector(vector, subCMap->vector);
+ }
+ subCMap->decRefCnt();
+}
+
+void CMap::useCMap(CMapCache *cache, Object *obj) {
+ CMap *subCMap;
+
+ subCMap = CMap::parse(cache, collection, obj);
+ if (!subCMap) {
+ return;
+ }
+ isIdent = subCMap->isIdent;
+ if (subCMap->vector) {
+ copyVector(vector, subCMap->vector);
+ }
subCMap->decRefCnt();
}
@@ -215,7 +273,7 @@ void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
copyVector(dest[i].vector, src[i].vector);
} else {
if (dest[i].isVector) {
- error(-1, "Collision in usecmap");
+ error(errSyntaxError, -1, "Collision in usecmap");
} else {
dest[i].cid = src[i].cid;
}
@@ -223,52 +281,32 @@ void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
}
}
-void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
- Guint nBytes) {
- Guint start2, end2;
- int startByte, endByte, i, j;
-
- if (nBytes > 1) {
- startByte = (start >> (8 * (nBytes - 1))) & 0xff;
- endByte = (end >> (8 * (nBytes - 1))) & 0xff;
- start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
- end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
- for (i = startByte; i <= endByte; ++i) {
- if (!vec[i].isVector) {
- vec[i].isVector = gTrue;
- vec[i].vector =
- (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
- for (j = 0; j < 256; ++j) {
- vec[i].vector[j].isVector = gFalse;
- vec[i].vector[j].cid = 0;
- }
- }
- addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
- }
- }
-}
-
void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
CMapVectorEntry *vec;
CID cid;
int byte;
- Guint i;
+ Guint i, j;
vec = vector;
for (i = nBytes - 1; i >= 1; --i) {
byte = (start >> (8 * i)) & 0xff;
if (!vec[byte].isVector) {
- error(-1, "Invalid CID (%0*x - %0*x) in CMap",
- 2*nBytes, start, 2*nBytes, end);
- return;
+ vec[byte].isVector = gTrue;
+ vec[byte].vector =
+ (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
+ for (j = 0; j < 256; ++j) {
+ vec[byte].vector[j].isVector = gFalse;
+ vec[byte].vector[j].cid = 0;
+ }
}
vec = vec[byte].vector;
}
cid = firstCID;
for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) {
if (vec[byte].isVector) {
- error(-1, "Invalid CID (%0*x - %0*x) in CMap",
- 2*nBytes, start, 2*nBytes, end);
+ error(errSyntaxError, -1,
+ "Invalid CID ({0:x} - {1:x} [{2:d} bytes]) in CMap",
+ start, end, nBytes);
} else {
vec[byte].cid = cid;
}
@@ -278,7 +316,9 @@ void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
CMap::~CMap() {
delete collection;
- delete cMapName;
+ if (cMapName) {
+ delete cMapName;
+ }
if (vector) {
freeCMapVector(vector);
}
@@ -327,31 +367,33 @@ GBool CMap::match(GString *collectionA, GString *cMapNameA) {
return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA);
}
-CID CMap::getCID(char *s, int len, int *nUsed) {
+CID CMap::getCID(char *s, int len, CharCode *c, int *nUsed) {
CMapVectorEntry *vec;
+ CharCode cc;
int n, i;
- if (!(vec = vector)) {
- // identity CMap
- *nUsed = 2;
- if (len < 2) {
- return 0;
- }
- return ((s[0] & 0xff) << 8) + (s[1] & 0xff);
- }
+ vec = vector;
+ cc = 0;
n = 0;
- while (1) {
- if (n >= len) {
- *nUsed = n;
- return 0;
- }
+ while (vec && n < len) {
i = s[n++] & 0xff;
+ cc = (cc << 8) | i;
if (!vec[i].isVector) {
+ *c = cc;
*nUsed = n;
return vec[i].cid;
}
vec = vec[i].vector;
}
+ if (isIdent && len >= 2) {
+ // identity CMap
+ *nUsed = 2;
+ *c = cc = ((s[0] & 0xff) << 8) + (s[1] & 0xff);
+ return cc;
+ }
+ *nUsed = 1;
+ *c = s[0] & 0xff;
+ return 0;
}
//------------------------------------------------------------------------
diff --git a/xpdf/CMap.h b/xpdf/CMap.h
index c321a57..f21b800 100644
--- a/xpdf/CMap.h
+++ b/xpdf/CMap.h
@@ -23,6 +23,8 @@
#endif
class GString;
+class Object;
+class Stream;
struct CMapVectorEntry;
class CMapCache;
@@ -31,11 +33,19 @@ class CMapCache;
class CMap {
public:
+ // Parse a CMap from <obj>, which can be a name or a stream. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA, Object *obj);
+
// Create the CMap specified by <collection> and <cMapName>. Sets
// the initial reference count to 1. Returns NULL on failure.
static CMap *parse(CMapCache *cache, GString *collectionA,
GString *cMapNameA);
+ // Parse a CMap from <str>. Sets the initial reference count to 1.
+ // Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA, Stream *str);
+
~CMap();
void incRefCnt();
@@ -49,26 +59,28 @@ public:
GBool match(GString *collectionA, GString *cMapNameA);
// Return the CID corresponding to the character code starting at
- // <s>, which contains <len> bytes. Sets *<nUsed> to the number of
- // bytes used by the char code.
- CID getCID(char *s, int len, int *nUsed);
+ // <s>, which contains <len> bytes. Sets *<c> to the char code, and
+ // *<nUsed> to the number of bytes used by the char code.
+ CID getCID(char *s, int len, CharCode *c, int *nUsed);
// Return the writing mode (0=horizontal, 1=vertical).
int getWMode() { return wMode; }
private:
+ void parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data);
CMap(GString *collectionA, GString *cMapNameA);
CMap(GString *collectionA, GString *cMapNameA, int wModeA);
void useCMap(CMapCache *cache, char *useName);
+ void useCMap(CMapCache *cache, Object *obj);
void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
- void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
- Guint nBytes);
void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
void freeCMapVector(CMapVectorEntry *vec);
GString *collection;
GString *cMapName;
+ GBool isIdent; // true if this CMap is an identity mapping,
+ // or is based on one (via usecmap)
int wMode; // writing mode (0=horizontal, 1=vertical)
CMapVectorEntry *vector; // vector for first byte (NULL for
// identity CMap)
diff --git a/xpdf/Catalog.cc b/xpdf/Catalog.cc
index de282c3..6c8a703 100644
--- a/xpdf/Catalog.cc
+++ b/xpdf/Catalog.cc
@@ -12,80 +12,112 @@
#pragma implementation
#endif
+#include <string.h>
#include <stddef.h>
+#include <limits.h>
#include "gmem.h"
+#include "gfile.h"
+#include "GList.h"
#include "Object.h"
+#include "CharTypes.h"
+#include "PDFDoc.h"
#include "XRef.h"
#include "Array.h"
#include "Dict.h"
#include "Page.h"
#include "Error.h"
#include "Link.h"
+#include "PDFDocEncoding.h"
#include "Catalog.h"
//------------------------------------------------------------------------
+// PageTreeNode
+//------------------------------------------------------------------------
+
+class PageTreeNode {
+public:
+
+ PageTreeNode(Ref refA, int countA, PageTreeNode *parentA);
+ ~PageTreeNode();
+
+ Ref ref;
+ int count;
+ PageTreeNode *parent;
+ GList *kids; // [PageTreeNode]
+ PageAttrs *attrs;
+};
+
+PageTreeNode::PageTreeNode(Ref refA, int countA, PageTreeNode *parentA) {
+ ref = refA;
+ count = countA;
+ parent = parentA;
+ kids = NULL;
+ attrs = NULL;
+}
+
+PageTreeNode::~PageTreeNode() {
+ delete attrs;
+ if (kids) {
+ deleteGList(kids, PageTreeNode);
+ }
+}
+
+//------------------------------------------------------------------------
+// EmbeddedFile
+//------------------------------------------------------------------------
+
+class EmbeddedFile {
+public:
+
+ EmbeddedFile(Unicode *nameA, int nameLenA, Object *streamRefA);
+ ~EmbeddedFile();
+
+ Unicode *name;
+ int nameLen;
+ Object streamRef;
+};
+
+EmbeddedFile::EmbeddedFile(Unicode *nameA, int nameLenA,
+ Object *streamRefA) {
+ name = nameA;
+ nameLen = nameLenA;
+ streamRefA->copy(&streamRef);
+}
+
+EmbeddedFile::~EmbeddedFile() {
+ gfree(name);
+ streamRef.free();
+}
+
+//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
-Catalog::Catalog(XRef *xrefA) {
- Object catDict, pagesDict, pagesDictRef;
+Catalog::Catalog(PDFDoc *docA) {
+ Object catDict;
Object obj, obj2;
- char *alreadyRead;
- int numPages0;
- int i;
ok = gTrue;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
+ pageTree = NULL;
pages = NULL;
pageRefs = NULL;
- numPages = pagesSize = 0;
+ numPages = 0;
baseURI = NULL;
+ embeddedFiles = NULL;
xref->getCatalog(&catDict);
if (!catDict.isDict()) {
- error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
+ error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})",
+ catDict.getTypeName());
goto err1;
}
// read page tree
- catDict.dictLookup("Pages", &pagesDict);
- // This should really be isDict("Pages"), but I've seen at least one
- // PDF file where the /Type entry is missing.
- if (!pagesDict.isDict()) {
- error(-1, "Top-level pages object is wrong type (%s)",
- pagesDict.getTypeName());
- goto err2;
- }
- pagesDict.dictLookup("Count", &obj);
- // some PDF files actually use real numbers here ("/Count 9.0")
- if (!obj.isNum()) {
- error(-1, "Page count in top-level pages object is wrong type (%s)",
- obj.getTypeName());
- goto err3;
- }
- pagesSize = numPages0 = (int)obj.getNum();
- obj.free();
- pages = (Page **)gmallocn(pagesSize, sizeof(Page *));
- pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref));
- for (i = 0; i < pagesSize; ++i) {
- pages[i] = NULL;
- pageRefs[i].num = -1;
- pageRefs[i].gen = -1;
- }
- 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");
+ if (!readPageTree(&catDict)) {
+ goto err1;
}
- pagesDict.free();
// read named destination dictionary
catDict.dictLookup("Dests", &dests);
@@ -105,6 +137,21 @@ Catalog::Catalog(XRef *xrefA) {
obj2.free();
}
obj.free();
+ if (!baseURI || baseURI->getLength() == 0) {
+ if (baseURI) {
+ delete baseURI;
+ }
+ if (doc->getFileName()) {
+ baseURI = makePathAbsolute(grabPath(doc->getFileName()->getCString()));
+ if (baseURI->getChar(0) == '/') {
+ baseURI->insert(0, "file://localhost");
+ } else {
+ baseURI->insert(0, "file://localhost/");
+ }
+ } else {
+ baseURI = new GString("file://localhost/");
+ }
+ }
// get the metadata stream
catDict.dictLookup("Metadata", &metadata);
@@ -118,13 +165,15 @@ Catalog::Catalog(XRef *xrefA) {
// get the AcroForm dictionary
catDict.dictLookup("AcroForm", &acroForm);
+ // get the OCProperties dictionary
+ catDict.dictLookup("OCProperties", &ocProperties);
+
+ // get the list of embedded files
+ readEmbeddedFileList(catDict.getDict());
+
catDict.free();
return;
- err3:
- obj.free();
- err2:
- pagesDict.free();
err1:
catDict.free();
dests.initNull();
@@ -135,8 +184,11 @@ Catalog::Catalog(XRef *xrefA) {
Catalog::~Catalog() {
int i;
+ if (pageTree) {
+ delete pageTree;
+ }
if (pages) {
- for (i = 0; i < pagesSize; ++i) {
+ for (i = 0; i < numPages; ++i) {
if (pages[i]) {
delete pages[i];
}
@@ -153,6 +205,31 @@ Catalog::~Catalog() {
structTreeRoot.free();
outline.free();
acroForm.free();
+ ocProperties.free();
+ if (embeddedFiles) {
+ deleteGList(embeddedFiles, EmbeddedFile);
+ }
+}
+
+Page *Catalog::getPage(int i) {
+ if (!pages[i-1]) {
+ loadPage(i);
+ }
+ return pages[i-1];
+}
+
+Ref *Catalog::getPageRef(int i) {
+ if (!pages[i-1]) {
+ loadPage(i);
+ }
+ return &pageRefs[i-1];
+}
+
+void Catalog::doneWithPage(int i) {
+ if (pages[i-1]) {
+ delete pages[i-1];
+ pages[i-1] = NULL;
+ }
}
GString *Catalog::readMetadata() {
@@ -166,7 +243,7 @@ GString *Catalog::readMetadata() {
}
dict = metadata.streamGetDict();
if (!dict->lookup("Subtype", &obj)->isName("XML")) {
- error(-1, "Unknown Metadata type: '%s'",
+ error(errSyntaxWarning, -1, "Unknown Metadata type: '{0:s}'",
obj.isName() ? obj.getName() : "???");
}
obj.free();
@@ -179,90 +256,13 @@ GString *Catalog::readMetadata() {
return s;
}
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
- char *alreadyRead) {
- Object kids;
- Object kid;
- Object kidRef;
- PageAttrs *attrs1, *attrs2;
- Page *page;
- int i, j;
-
- attrs1 = new PageAttrs(attrs, pagesDict);
- pagesDict->lookup("Kids", &kids);
- if (!kids.isArray()) {
- error(-1, "Kids object (page %d) is wrong type (%s)",
- start+1, kids.getTypeName());
- 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());
- page = new Page(xref, start+1, kid.getDict(), attrs2);
- if (!page->isOk()) {
- ++start;
- goto err3;
- }
- if (start >= pagesSize) {
- pagesSize += 32;
- pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *));
- pageRefs = (Ref *)greallocn(pageRefs, pagesSize, sizeof(Ref));
- for (j = pagesSize - 32; j < pagesSize; ++j) {
- pages[j] = NULL;
- pageRefs[j].num = -1;
- pageRefs[j].gen = -1;
- }
- }
- pages[start] = page;
- if (kidRef.isRef()) {
- pageRefs[start].num = kidRef.getRefNum();
- pageRefs[start].gen = kidRef.getRefGen();
- }
- ++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, alreadyRead))
- < 0)
- goto err2;
- } else {
- error(-1, "Kid object (page %d) is wrong type (%s)",
- start+1, kid.getTypeName());
- }
- kid.free();
- kidRef.free();
- }
- delete attrs1;
- kids.free();
- return start;
-
- err3:
- delete page;
- err2:
- kid.free();
- err1:
- kids.free();
- delete attrs1;
- ok = gFalse;
- return -1;
-}
-
int Catalog::findPage(int num, int gen) {
int i;
for (i = 0; i < numPages; ++i) {
+ if (!pages[i]) {
+ loadPage(i+1);
+ }
if (pageRefs[i].num == num && pageRefs[i].gen == gen)
return i + 1;
}
@@ -299,10 +299,10 @@ LinkDest *Catalog::findDest(GString *name) {
if (obj1.dictLookup("D", &obj2)->isArray())
dest = new LinkDest(obj2.getArray());
else
- error(-1, "Bad named destination value");
+ error(errSyntaxWarning, -1, "Bad named destination value");
obj2.free();
} else {
- error(-1, "Bad named destination value");
+ error(errSyntaxWarning, -1, "Bad named destination value");
}
obj1.free();
if (dest && !dest->isOk()) {
@@ -372,3 +372,367 @@ Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
return obj;
}
+
+GBool Catalog::readPageTree(Object *catDict) {
+ Object topPagesRef, topPagesObj, countObj;
+ int i;
+
+ if (!catDict->dictLookupNF("Pages", &topPagesRef)->isRef()) {
+ error(errSyntaxError, -1, "Top-level pages reference is wrong type ({0:s})",
+ topPagesRef.getTypeName());
+ topPagesRef.free();
+ return gFalse;
+ }
+ if (!topPagesRef.fetch(xref, &topPagesObj)->isDict()) {
+ error(errSyntaxError, -1, "Top-level pages object is wrong type ({0:s})",
+ topPagesObj.getTypeName());
+ topPagesObj.free();
+ topPagesRef.free();
+ return gFalse;
+ }
+ if (topPagesObj.dictLookup("Count", &countObj)->isInt()) {
+ numPages = countObj.getInt();
+ if (numPages == 0) {
+ // Acrobat apparently scans the page tree if it sees a zero count
+ numPages = countPageTree(&topPagesObj);
+ }
+ } else {
+ // assume we got a Page node instead of a Pages node
+ numPages = 1;
+ }
+ countObj.free();
+ if (numPages < 0) {
+ error(errSyntaxError, -1, "Invalid page count");
+ topPagesObj.free();
+ topPagesRef.free();
+ numPages = 0;
+ return gFalse;
+ }
+ pageTree = new PageTreeNode(topPagesRef.getRef(), numPages, NULL);
+ topPagesObj.free();
+ topPagesRef.free();
+ pages = (Page **)greallocn(pages, numPages, sizeof(Page *));
+ pageRefs = (Ref *)greallocn(pageRefs, numPages, sizeof(Ref));
+ for (i = 0; i < numPages; ++i) {
+ pages[i] = NULL;
+ pageRefs[i].num = -1;
+ pageRefs[i].gen = -1;
+ }
+ return gTrue;
+}
+
+int Catalog::countPageTree(Object *pagesObj) {
+ Object kids, kid;
+ int n, n2, i;
+
+ if (!pagesObj->isDict()) {
+ return 0;
+ }
+ if (pagesObj->dictLookup("Kids", &kids)->isArray()) {
+ n = 0;
+ for (i = 0; i < kids.arrayGetLength(); ++i) {
+ kids.arrayGet(i, &kid);
+ n2 = countPageTree(&kid);
+ if (n2 < INT_MAX - n) {
+ n += n2;
+ } else {
+ error(errSyntaxError, -1, "Page tree contains too many pages");
+ n = INT_MAX;
+ }
+ kid.free();
+ }
+ } else {
+ n = 1;
+ }
+ kids.free();
+ return n;
+}
+
+void Catalog::loadPage(int pg) {
+ loadPage2(pg, pg - 1, pageTree);
+}
+
+void Catalog::loadPage2(int pg, int relPg, PageTreeNode *node) {
+ Object pageRefObj, pageObj, kidsObj, kidRefObj, kidObj, countObj;
+ PageTreeNode *kidNode, *p;
+ PageAttrs *attrs;
+ int count, i;
+
+ if (relPg >= node->count) {
+ error(errSyntaxError, -1, "Internal error in page tree");
+ pages[pg-1] = new Page(doc, pg);
+ return;
+ }
+
+ // if this node has not been filled in yet, it's either a leaf node
+ // or an unread internal node
+ if (!node->kids) {
+
+ // check for a loop in the page tree
+ for (p = node->parent; p; p = p->parent) {
+ if (node->ref.num == p->ref.num && node->ref.gen == p->ref.gen) {
+ error(errSyntaxError, -1, "Loop in Pages tree");
+ pages[pg-1] = new Page(doc, pg);
+ return;
+ }
+ }
+
+ // fetch the Page/Pages object
+ pageRefObj.initRef(node->ref.num, node->ref.gen);
+ if (!pageRefObj.fetch(xref, &pageObj)->isDict()) {
+ error(errSyntaxError, -1, "Page tree object is wrong type ({0:s})",
+ pageObj.getTypeName());
+ pageObj.free();
+ pageRefObj.free();
+ pages[pg-1] = new Page(doc, pg);
+ return;
+ }
+
+ // merge the PageAttrs
+ attrs = new PageAttrs(node->parent ? node->parent->attrs
+ : (PageAttrs *)NULL,
+ pageObj.getDict());
+
+ // if "Kids" exists, it's an internal node
+ if (pageObj.dictLookup("Kids", &kidsObj)->isArray()) {
+
+ // save the PageAttrs
+ node->attrs = attrs;
+
+ // read the kids
+ node->kids = new GList();
+ for (i = 0; i < kidsObj.arrayGetLength(); ++i) {
+ if (kidsObj.arrayGetNF(i, &kidRefObj)->isRef()) {
+ if (kidRefObj.fetch(xref, &kidObj)->isDict()) {
+ if (kidObj.dictLookup("Count", &countObj)->isInt()) {
+ count = countObj.getInt();
+ } else {
+ count = 1;
+ }
+ countObj.free();
+ node->kids->append(new PageTreeNode(kidRefObj.getRef(), count,
+ node));
+ } else {
+ error(errSyntaxError, -1, "Page tree object is wrong type ({0:s})",
+ kidObj.getTypeName());
+ }
+ kidObj.free();
+ } else {
+ error(errSyntaxError, -1,
+ "Page tree reference is wrong type ({0:s})",
+ kidRefObj.getTypeName());
+ }
+ kidRefObj.free();
+ }
+
+ } else {
+
+ // create the Page object
+ pageRefs[pg-1] = node->ref;
+ pages[pg-1] = new Page(doc, pg, pageObj.getDict(), attrs);
+ if (!pages[pg-1]->isOk()) {
+ delete pages[pg-1];
+ pages[pg-1] = new Page(doc, pg);
+ }
+
+ }
+
+ kidsObj.free();
+ pageObj.free();
+ pageRefObj.free();
+ }
+
+ // recursively descend the tree
+ if (node->kids) {
+ for (i = 0; i < node->kids->getLength(); ++i) {
+ kidNode = (PageTreeNode *)node->kids->get(i);
+ if (relPg < kidNode->count) {
+ loadPage2(pg, relPg, kidNode);
+ break;
+ }
+ relPg -= kidNode->count;
+ }
+
+ // this will only happen if the page tree is invalid
+ // (i.e., parent count > sum of children counts)
+ if (i == node->kids->getLength()) {
+ error(errSyntaxError, -1, "Invalid page count in page tree");
+ pages[pg-1] = new Page(doc, pg);
+ }
+ }
+}
+
+void Catalog::readEmbeddedFileList(Dict *catDict) {
+ Object obj1, obj2;
+ char *touchedObjs;
+
+ // read the embedded file name tree
+ if (catDict->lookup("Names", &obj1)->isDict()) {
+ if (obj1.dictLookup("EmbeddedFiles", &obj2)->isDict()) {
+ readEmbeddedFileTree(&obj2);
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ // look for file attachment annotations
+ touchedObjs = (char *)gmalloc(xref->getNumObjects());
+ memset(touchedObjs, 0, xref->getNumObjects());
+ readFileAttachmentAnnots(catDict->lookupNF("Pages", &obj1), touchedObjs);
+ obj1.free();
+ gfree(touchedObjs);
+}
+
+void Catalog::readEmbeddedFileTree(Object *node) {
+ Object kidsObj, kidObj;
+ Object namesObj, nameObj, fileSpecObj;
+ int i;
+
+ if (node->dictLookup("Kids", &kidsObj)->isArray()) {
+ for (i = 0; i < kidsObj.arrayGetLength(); ++i) {
+ if (kidsObj.arrayGet(i, &kidObj)->isDict()) {
+ readEmbeddedFileTree(&kidObj);
+ }
+ kidObj.free();
+ }
+ } else {
+ if (node->dictLookup("Names", &namesObj)->isArray()) {
+ for (i = 0; i+1 < namesObj.arrayGetLength(); ++i) {
+ namesObj.arrayGet(i, &nameObj);
+ namesObj.arrayGet(i+1, &fileSpecObj);
+ readEmbeddedFile(&fileSpecObj, &nameObj);
+ nameObj.free();
+ fileSpecObj.free();
+ }
+ }
+ namesObj.free();
+ }
+ kidsObj.free();
+}
+
+void Catalog::readFileAttachmentAnnots(Object *pageNodeRef,
+ char *touchedObjs) {
+ Object pageNode, kids, kid, annots, annot, subtype, fileSpec, contents;
+ int i;
+
+ // check for a page tree loop
+ if (pageNodeRef->isRef()) {
+ if (touchedObjs[pageNodeRef->getRefNum()]) {
+ return;
+ }
+ touchedObjs[pageNodeRef->getRefNum()] = 1;
+ xref->fetch(pageNodeRef->getRefNum(), pageNodeRef->getRefGen(), &pageNode);
+ } else {
+ pageNodeRef->copy(&pageNode);
+ }
+
+ if (pageNode.isDict()) {
+ if (pageNode.dictLookup("Kids", &kids)->isArray()) {
+ for (i = 0; i < kids.arrayGetLength(); ++i) {
+ readFileAttachmentAnnots(kids.arrayGetNF(i, &kid), touchedObjs);
+ kid.free();
+ }
+ } else {
+ if (pageNode.dictLookup("Annots", &annots)->isArray()) {
+ for (i = 0; i < annots.arrayGetLength(); ++i) {
+ if (annots.arrayGet(i, &annot)->isDict()) {
+ if (annot.dictLookup("Subtype", &subtype)
+ ->isName("FileAttachment")) {
+ if (annot.dictLookup("FS", &fileSpec)) {
+ readEmbeddedFile(&fileSpec,
+ annot.dictLookup("Contents", &contents));
+ contents.free();
+ }
+ fileSpec.free();
+ }
+ subtype.free();
+ }
+ annot.free();
+ }
+ }
+ annots.free();
+ }
+ kids.free();
+ }
+
+ pageNode.free();
+}
+
+void Catalog::readEmbeddedFile(Object *fileSpec, Object *name1) {
+ Object name2, efObj, streamObj;
+ GString *s;
+ Unicode *name;
+ int nameLen, i;
+
+ if (fileSpec->isDict()) {
+ if (fileSpec->dictLookup("UF", &name2)->isString()) {
+ s = name2.getString();
+ } else {
+ name2.free();
+ if (fileSpec->dictLookup("F", &name2)->isString()) {
+ s = name2.getString();
+ } else if (name1 && name1->isString()) {
+ s = name1->getString();
+ } else {
+ s = NULL;
+ }
+ }
+ if (s) {
+ if ((s->getChar(0) & 0xff) == 0xfe &&
+ (s->getChar(1) & 0xff) == 0xff) {
+ nameLen = (s->getLength() - 2) / 2;
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ for (i = 0; i < nameLen; ++i) {
+ name[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
+ (s->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ nameLen = s->getLength();
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ for (i = 0; i < nameLen; ++i) {
+ name[i] = pdfDocEncoding[s->getChar(i) & 0xff];
+ }
+ }
+ } else {
+ nameLen = 1;
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ name[0] = '?';
+ }
+ name2.free();
+ if (fileSpec->dictLookup("EF", &efObj)->isDict()) {
+ if (efObj.dictLookupNF("F", &streamObj)->isRef()) {
+ if (!embeddedFiles) {
+ embeddedFiles = new GList();
+ }
+ embeddedFiles->append(new EmbeddedFile(name, nameLen, &streamObj));
+ } else {
+ gfree(name);
+ }
+ streamObj.free();
+ } else {
+ gfree(name);
+ }
+ efObj.free();
+ }
+}
+
+int Catalog::getNumEmbeddedFiles() {
+ return embeddedFiles ? embeddedFiles->getLength() : 0;
+}
+
+Unicode *Catalog::getEmbeddedFileName(int idx) {
+ return ((EmbeddedFile *)embeddedFiles->get(idx))->name;
+}
+
+int Catalog::getEmbeddedFileNameLength(int idx) {
+ return ((EmbeddedFile *)embeddedFiles->get(idx))->nameLen;
+}
+
+Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) {
+ ((EmbeddedFile *)embeddedFiles->get(idx))->streamRef.fetch(xref, strObj);
+ if (!strObj->isStream()) {
+ strObj->free();
+ return NULL;
+ }
+ return strObj;
+}
diff --git a/xpdf/Catalog.h b/xpdf/Catalog.h
index 6403194..efbbeda 100644
--- a/xpdf/Catalog.h
+++ b/xpdf/Catalog.h
@@ -15,12 +15,17 @@
#pragma interface
#endif
+#include "CharTypes.h"
+
+class GList;
+class PDFDoc;
class XRef;
class Object;
class Page;
class PageAttrs;
struct Ref;
class LinkDest;
+class PageTreeNode;
//------------------------------------------------------------------------
// Catalog
@@ -30,7 +35,7 @@ class Catalog {
public:
// Constructor.
- Catalog(XRef *xrefA);
+ Catalog(PDFDoc *docA);
// Destructor.
~Catalog();
@@ -42,10 +47,14 @@ public:
int getNumPages() { return numPages; }
// Get a page.
- Page *getPage(int i) { return pages[i-1]; }
+ Page *getPage(int i);
// Get the reference for a page object.
- Ref *getPageRef(int i) { return &pageRefs[i-1]; }
+ Ref *getPageRef(int i);
+
+ // Remove a page from the catalog. (It can be reloaded later by
+ // calling getPage).
+ void doneWithPage(int i);
// Return base URI, or NULL if none.
GString *getBaseURI() { return baseURI; }
@@ -73,9 +82,19 @@ public:
Object *getAcroForm() { return &acroForm; }
+ Object *getOCProperties() { return &ocProperties; }
+
+ // Get the list of embedded files.
+ int getNumEmbeddedFiles();
+ Unicode *getEmbeddedFileName(int idx);
+ int getEmbeddedFileNameLength(int idx);
+ Object *getEmbeddedFileStreamObj(int idx, Object *strObj);
+
private:
+ PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
+ PageTreeNode *pageTree; // the page tree
Page **pages; // array of pages
Ref *pageRefs; // object ID for each page
int numPages; // number of pages
@@ -87,11 +106,20 @@ private:
Object structTreeRoot; // structure tree root dictionary
Object outline; // outline dictionary
Object acroForm; // AcroForm dictionary
+ Object ocProperties; // OCProperties dictionary
+ GList *embeddedFiles; // embedded file list [EmbeddedFile]
GBool ok; // true if catalog is valid
- int readPageTree(Dict *pages, PageAttrs *attrs, int start,
- char *alreadyRead);
Object *findDestInTree(Object *tree, GString *name, Object *obj);
+ GBool readPageTree(Object *catDict);
+ int countPageTree(Object *pagesObj);
+ void loadPage(int pg);
+ void loadPage2(int pg, int relPg, PageTreeNode *node);
+ void readEmbeddedFileList(Dict *catDict);
+ void readEmbeddedFileTree(Object *node);
+ void readFileAttachmentAnnots(Object *pageNodeRef,
+ char *touchedObjs);
+ void readEmbeddedFile(Object *fileSpec, Object *name1);
};
#endif
diff --git a/xpdf/CharCodeToUnicode.cc b/xpdf/CharCodeToUnicode.cc
index 3702a16..ff40595 100644
--- a/xpdf/CharCodeToUnicode.cc
+++ b/xpdf/CharCodeToUnicode.cc
@@ -54,6 +54,47 @@ static int getCharFromFile(void *data) {
//------------------------------------------------------------------------
+static int hexCharVals[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 1x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 2x
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 3x
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5x
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 8x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 9x
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ax
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bx
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Cx
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Dx
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ex
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // Fx
+};
+
+// Parse a <len>-byte hex string <s> into *<val>. Returns false on
+// error.
+static GBool parseHex(char *s, int len, Guint *val) {
+ int i, x;
+
+ *val = 0;
+ for (i = 0; i < len; ++i) {
+ x = hexCharVals[s[i] & 0xff];
+ if (x < 0) {
+ return gFalse;
+ }
+ *val = (*val << 4) + x;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+
+CharCodeToUnicode *CharCodeToUnicode::makeIdentityMapping() {
+ return new CharCodeToUnicode();
+}
+
CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
GString *collection) {
FILE *f;
@@ -63,9 +104,9 @@ CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
Unicode u;
CharCodeToUnicode *ctu;
- if (!(f = fopen(fileName->getCString(), "r"))) {
- error(-1, "Couldn't open cidToUnicode file '%s'",
- fileName->getCString());
+ if (!(f = openFile(fileName->getCString(), "r"))) {
+ error(errSyntaxError, -1, "Couldn't open cidToUnicode file '{0:t}'",
+ fileName);
return NULL;
}
@@ -81,8 +122,9 @@ CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
if (sscanf(buf, "%x", &u) == 1) {
mapA[mapLenA] = u;
} else {
- error(-1, "Bad line (%d) in cidToUnicode file '%s'",
- (int)(mapLenA + 1), fileName->getCString());
+ error(errSyntaxWarning, -1,
+ "Bad line ({0:d}) in cidToUnicode file '{1:t}'",
+ (int)(mapLenA + 1), fileName);
mapA[mapLenA] = 0;
}
++mapLenA;
@@ -108,9 +150,9 @@ CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
CharCodeToUnicode *ctu;
int line, n, i;
- if (!(f = fopen(fileName->getCString(), "r"))) {
- error(-1, "Couldn't open unicodeToUnicode file '%s'",
- fileName->getCString());
+ if (!(f = openFile(fileName->getCString(), "r"))) {
+ error(errSyntaxError, -1, "Couldn't open unicodeToUnicode file '{0:t}'",
+ fileName);
return NULL;
}
@@ -125,9 +167,10 @@ CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
while (getLine(buf, sizeof(buf), f)) {
++line;
if (!(tok = strtok(buf, " \t\r\n")) ||
- sscanf(tok, "%x", &u0) != 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
+ !parseHex(tok, strlen(tok), &u0)) {
+ error(errSyntaxWarning, -1,
+ "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
+ line, fileName);
continue;
}
n = 0;
@@ -135,16 +178,18 @@ CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
if (!(tok = strtok(NULL, " \t\r\n"))) {
break;
}
- if (sscanf(tok, "%x", &uBuf[n]) != 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
+ if (!parseHex(tok, strlen(tok), &uBuf[n])) {
+ error(errSyntaxWarning, -1,
+ "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
+ line, fileName);
break;
}
++n;
}
if (n < 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
+ error(errSyntaxWarning, -1,
+ "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
+ line, fileName);
continue;
}
if (u0 >= size) {
@@ -208,13 +253,13 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
int nBits) {
PSTokenizer *pst;
char tok1[256], tok2[256], tok3[256];
- int nDigits, n1, n2, n3;
+ int n1, n2, n3;
CharCode i;
- CharCode code1, code2;
+ CharCode maxCode, code1, code2;
GString *name;
FILE *f;
- nDigits = nBits / 4;
+ maxCode = (nBits == 8) ? 0xff : (nBits == 16) ? 0xffff : 0xffffffff;
pst = new PSTokenizer(getCharFunc, data);
pst->getToken(tok1, sizeof(tok1), &n1);
while (pst->getToken(tok2, sizeof(tok2), &n2)) {
@@ -225,8 +270,9 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
parseCMap1(&getCharFromFile, f, nBits);
fclose(f);
} else {
- error(-1, "Couldn't find ToUnicode CMap file for '%s'",
- name->getCString());
+ error(errSyntaxError, -1,
+ "Couldn't find ToUnicode CMap file for '{1:t}'",
+ name);
}
delete name;
}
@@ -238,19 +284,26 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
}
if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
!strcmp(tok2, "endbfchar")) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfchar block in ToUnicode CMap");
break;
}
- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
+ if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
tok2[0] == '<' && tok2[n2 - 1] == '>')) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
tok1[n1 - 1] = tok2[n2 - 1] = '\0';
- if (sscanf(tok1 + 1, "%x", &code1) != 1) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ if (!parseHex(tok1 + 1, n1 - 2, &code1)) {
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
+ if (code1 > maxCode) {
+ error(errSyntaxWarning, -1,
+ "Invalid entry in bfchar block in ToUnicode CMap");
+ }
addMapping(code1, tok2 + 1, n2 - 2, 0);
}
pst->getToken(tok1, sizeof(tok1), &n1);
@@ -263,20 +316,33 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
!strcmp(tok2, "endbfrange") ||
!pst->getToken(tok3, sizeof(tok3), &n3) ||
!strcmp(tok3, "endbfrange")) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfrange block in ToUnicode CMap");
break;
}
- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
- n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
+ tok2[0] == '<' && tok2[n2 - 1] == '>')) {
+ error(errSyntaxWarning,
+ -1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
tok1[n1 - 1] = tok2[n2 - 1] = '\0';
- if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
- sscanf(tok2 + 1, "%x", &code2) != 1) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ if (!parseHex(tok1 + 1, n1 - 2, &code1) ||
+ !parseHex(tok2 + 1, n2 - 2, &code2)) {
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
+ if (code1 > maxCode || code2 > maxCode) {
+ error(errSyntaxWarning, -1,
+ "Invalid entry in bfrange block in ToUnicode CMap");
+ if (code1 > maxCode) {
+ code1 = maxCode;
+ }
+ if (code2 > maxCode) {
+ code2 = maxCode;
+ }
+ }
if (!strcmp(tok3, "[")) {
i = 0;
while (pst->getToken(tok1, sizeof(tok1), &n1) &&
@@ -288,7 +354,8 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
tok1[n1 - 1] = '\0';
addMapping(code1 + i, tok1 + 1, n1 - 2, 0);
} else {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfrange block in ToUnicode CMap");
}
++i;
}
@@ -299,7 +366,8 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
}
} else {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ error(errSyntaxWarning, -1,
+ "Illegal entry in bfrange block in ToUnicode CMap");
}
}
pst->getToken(tok1, sizeof(tok1), &n1);
@@ -314,20 +382,27 @@ void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
int offset) {
CharCode oldLen, i;
Unicode u;
- char uHex[5];
int j;
+ if (code > 0xffffff) {
+ // This is an arbitrary limit to avoid integer overflow issues.
+ // (I've seen CMaps with mappings for <ffffffff>.)
+ return;
+ }
if (code >= mapLen) {
oldLen = mapLen;
- mapLen = (code + 256) & ~255;
+ mapLen = mapLen ? 2 * mapLen : 256;
+ if (code >= mapLen) {
+ mapLen = (code + 256) & ~255;
+ }
map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode));
for (i = oldLen; i < mapLen; ++i) {
map[i] = 0;
}
}
if (n <= 4) {
- if (sscanf(uStr, "%x", &u) != 1) {
- error(-1, "Illegal entry in ToUnicode CMap");
+ if (!parseHex(uStr, n, &u)) {
+ error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap");
return;
}
map[code] = u + offset;
@@ -339,12 +414,13 @@ void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
}
map[code] = 0;
sMap[sMapLen].c = code;
- sMap[sMapLen].len = n / 4;
- for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
- strncpy(uHex, uStr + j*4, 4);
- uHex[4] = '\0';
- if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal entry in ToUnicode CMap");
+ if ((sMap[sMapLen].len = n / 4) > maxUnicodeString) {
+ sMap[sMapLen].len = maxUnicodeString;
+ }
+ for (j = 0; j < sMap[sMapLen].len; ++j) {
+ if (!parseHex(uStr + j*4, 4, &sMap[sMapLen].u[j])) {
+ error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap");
+ return;
}
}
sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset;
@@ -352,6 +428,18 @@ void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
}
}
+CharCodeToUnicode::CharCodeToUnicode() {
+ tag = NULL;
+ map = NULL;
+ mapLen = 0;
+ sMap = NULL;
+ sMapLen = sMapSize = 0;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
CharCodeToUnicode::CharCodeToUnicode(GString *tagA) {
CharCode i;
@@ -395,9 +483,7 @@ CharCodeToUnicode::~CharCodeToUnicode() {
delete tag;
}
gfree(map);
- if (sMap) {
- gfree(sMap);
- }
+ gfree(sMap);
#if MULTITHREADED
gDestroyMutex(&mutex);
#endif
@@ -435,6 +521,9 @@ GBool CharCodeToUnicode::match(GString *tagA) {
void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
int i, j;
+ if (!map) {
+ return;
+ }
if (len == 1) {
map[c] = u[0];
} else {
@@ -463,6 +552,10 @@ void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
int i, j;
+ if (!map) {
+ u[0] = (Unicode)c;
+ return 1;
+ }
if (c >= mapLen) {
return 0;
}
diff --git a/xpdf/CharCodeToUnicode.h b/xpdf/CharCodeToUnicode.h
index 04852ae..b4ccd04 100644
--- a/xpdf/CharCodeToUnicode.h
+++ b/xpdf/CharCodeToUnicode.h
@@ -30,6 +30,9 @@ struct CharCodeToUnicodeString;
class CharCodeToUnicode {
public:
+ // Create an identity mapping (Unicode = CharCode).
+ static CharCodeToUnicode *makeIdentityMapping();
+
// Read the CID-to-Unicode mapping for <collection> from the file
// specified by <fileName>. Sets the initial reference count to 1.
// Returns NULL on failure.
@@ -75,6 +78,7 @@ private:
void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits);
void addMapping(CharCode code, char *uStr, int n, int offset);
+ CharCodeToUnicode();
CharCodeToUnicode(GString *tagA);
CharCodeToUnicode(GString *tagA, Unicode *mapA,
CharCode mapLenA, GBool copyMap,
diff --git a/xpdf/Decrypt.cc b/xpdf/Decrypt.cc
index 0320589..afde3c3 100644
--- a/xpdf/Decrypt.cc
+++ b/xpdf/Decrypt.cc
@@ -16,12 +16,13 @@
#include "gmem.h"
#include "Decrypt.h"
-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 void aes256KeyExpansion(DecryptAES256State *s,
+ Guchar *objKey, int objKeyLen);
+static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last);
+static void sha256(Guchar *msg, int msgLen, Guchar *hash);
static Guchar passwordPad[32] = {
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
@@ -36,67 +37,139 @@ static Guchar passwordPad[32] = {
GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
+ GString *ownerEnc, GString *userEnc,
int permissions, GString *fileID,
GString *ownerPassword, GString *userPassword,
Guchar *fileKey, GBool encryptMetadata,
GBool *ownerPasswordOk) {
- Guchar test[32], test2[32];
+ DecryptAES256State state;
+ Guchar test[127 + 56], test2[32];
GString *userPassword2;
Guchar fState[256];
Guchar tmpKey[16];
Guchar fx, fy;
int len, i, j;
- // try using the supplied owner password to generate the user password
*ownerPasswordOk = gFalse;
- if (ownerPassword) {
- len = ownerPassword->getLength();
- if (len < 32) {
+
+ if (encRevision == 5) {
+
+ // check the owner password
+ if (ownerPassword) {
+ //~ this is supposed to convert the password to UTF-8 using "SASLprep"
+ len = ownerPassword->getLength();
+ if (len > 127) {
+ len = 127;
+ }
memcpy(test, ownerPassword->getCString(), len);
- memcpy(test + len, passwordPad, 32 - len);
- } else {
- memcpy(test, ownerPassword->getCString(), 32);
+ memcpy(test + len, ownerKey->getCString() + 32, 8);
+ memcpy(test + len + 8, userKey->getCString(), 48);
+ sha256(test, len + 56, test);
+ if (!memcmp(test, ownerKey->getCString(), 32)) {
+
+ // compute the file key from the owner password
+ memcpy(test, ownerPassword->getCString(), len);
+ memcpy(test + len, ownerKey->getCString() + 40, 8);
+ memcpy(test + len + 8, userKey->getCString(), 48);
+ sha256(test, len + 56, test);
+ aes256KeyExpansion(&state, test, 32);
+ for (i = 0; i < 16; ++i) {
+ state.cbc[i] = 0;
+ }
+ aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString(), gFalse);
+ memcpy(fileKey, state.buf, 16);
+ aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString() + 16,
+ gFalse);
+ memcpy(fileKey + 16, state.buf, 16);
+
+ *ownerPasswordOk = gTrue;
+ return gTrue;
+ }
}
- md5(test, 32, test);
- if (encRevision == 3) {
- for (i = 0; i < 50; ++i) {
- md5(test, 16, test);
+
+ // check the user password
+ if (userPassword) {
+ //~ this is supposed to convert the password to UTF-8 using "SASLprep"
+ len = userPassword->getLength();
+ if (len > 127) {
+ len = 127;
+ }
+ memcpy(test, userPassword->getCString(), len);
+ memcpy(test + len, userKey->getCString() + 32, 8);
+ sha256(test, len + 8, test);
+ if (!memcmp(test, userKey->getCString(), 32)) {
+
+ // compute the file key from the user password
+ memcpy(test, userPassword->getCString(), len);
+ memcpy(test + len, userKey->getCString() + 40, 8);
+ sha256(test, len + 8, test);
+ aes256KeyExpansion(&state, test, 32);
+ for (i = 0; i < 16; ++i) {
+ state.cbc[i] = 0;
+ }
+ aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse);
+ memcpy(fileKey, state.buf, 16);
+ aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16,
+ gFalse);
+ memcpy(fileKey + 16, state.buf, 16);
+
+ return gTrue;
}
}
- if (encRevision == 2) {
- rc4InitKey(test, keyLength, fState);
- fx = fy = 0;
- for (i = 0; i < 32; ++i) {
- test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
+
+ return gFalse;
+ } else {
+
+ // try using the supplied owner password to generate the user password
+ if (ownerPassword) {
+ len = ownerPassword->getLength();
+ if (len < 32) {
+ memcpy(test, ownerPassword->getCString(), len);
+ memcpy(test + len, passwordPad, 32 - len);
+ } else {
+ memcpy(test, ownerPassword->getCString(), 32);
}
- } else {
- memcpy(test2, ownerKey->getCString(), 32);
- for (i = 19; i >= 0; --i) {
- for (j = 0; j < keyLength; ++j) {
- tmpKey[j] = test[j] ^ i;
+ md5(test, 32, test);
+ if (encRevision == 3) {
+ for (i = 0; i < 50; ++i) {
+ md5(test, keyLength, test);
}
- rc4InitKey(tmpKey, keyLength, fState);
+ }
+ if (encRevision == 2) {
+ rc4InitKey(test, keyLength, fState);
fx = fy = 0;
- for (j = 0; j < 32; ++j) {
- test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
+ for (i = 0; i < 32; ++i) {
+ test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
+ }
+ } else {
+ memcpy(test2, ownerKey->getCString(), 32);
+ for (i = 19; i >= 0; --i) {
+ for (j = 0; j < keyLength; ++j) {
+ tmpKey[j] = test[j] ^ i;
+ }
+ rc4InitKey(tmpKey, keyLength, fState);
+ fx = fy = 0;
+ for (j = 0; j < 32; ++j) {
+ test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
+ }
}
}
- }
- userPassword2 = new GString((char *)test2, 32);
- if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
- permissions, fileID, userPassword2, fileKey,
- encryptMetadata)) {
- *ownerPasswordOk = gTrue;
+ userPassword2 = new GString((char *)test2, 32);
+ if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+ permissions, fileID, userPassword2, fileKey,
+ encryptMetadata)) {
+ *ownerPasswordOk = gTrue;
+ delete userPassword2;
+ return gTrue;
+ }
delete userPassword2;
- return gTrue;
}
- delete userPassword2;
- }
- // try using the supplied user password
- return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
- permissions, fileID, userPassword, fileKey,
- encryptMetadata);
+ // try using the supplied user password
+ return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+ permissions, fileID, userPassword, fileKey,
+ encryptMetadata);
+ }
}
GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
@@ -186,7 +259,7 @@ DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey,
int objNum, int objGen):
FilterStream(strA)
{
- int n, i;
+ int i;
algo = algoA;
@@ -194,23 +267,36 @@ DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey,
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) {
+ switch (algo) {
+ case cryptRC4:
+ 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);
+ if ((objKeyLength = keyLength + 5) > 16) {
+ objKeyLength = 16;
+ }
+ break;
+ case cryptAES:
+ 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;
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;
+ md5(objKey, keyLength + 9, objKey);
+ if ((objKeyLength = keyLength + 5) > 16) {
+ objKeyLength = 16;
+ }
+ break;
+ case cryptAES256:
+ objKeyLength = keyLength;
+ break;
}
}
@@ -235,6 +321,13 @@ void DecryptStream::reset() {
}
state.aes.bufIdx = 16;
break;
+ case cryptAES256:
+ aes256KeyExpansion(&state.aes256, objKey, objKeyLength);
+ for (i = 0; i < 16; ++i) {
+ state.aes256.cbc[i] = str->getChar();
+ }
+ state.aes256.bufIdx = 16;
+ break;
}
}
@@ -271,6 +364,22 @@ int DecryptStream::getChar() {
c = state.aes.buf[state.aes.bufIdx++];
}
break;
+ case cryptAES256:
+ if (state.aes256.bufIdx == 16) {
+ for (i = 0; i < 16; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ return EOF;
+ }
+ in[i] = (Guchar)c;
+ }
+ aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF);
+ }
+ if (state.aes256.bufIdx == 16) {
+ c = EOF;
+ } else {
+ c = state.aes256.buf[state.aes256.bufIdx++];
+ }
+ break;
}
return c;
}
@@ -307,6 +416,22 @@ int DecryptStream::lookChar() {
c = state.aes.buf[state.aes.bufIdx];
}
break;
+ case cryptAES256:
+ if (state.aes256.bufIdx == 16) {
+ for (i = 0; i < 16; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ return EOF;
+ }
+ in[i] = c;
+ }
+ aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF);
+ }
+ if (state.aes256.bufIdx == 16) {
+ c = EOF;
+ } else {
+ c = state.aes256.buf[state.aes256.bufIdx];
+ }
+ break;
}
return c;
}
@@ -319,7 +444,7 @@ GBool DecryptStream::isBinary(GBool last) {
// RC4-compatible decryption
//------------------------------------------------------------------------
-static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
+void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
Guchar index1, index2;
Guchar t;
int i;
@@ -336,7 +461,7 @@ static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
}
}
-static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
+Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
Guchar x1, y1, tx, ty;
x1 = *x = (*x + 1) % 256;
@@ -596,6 +721,92 @@ static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) {
s->bufIdx = 0;
if (last) {
n = s->buf[15];
+ if (n < 1 || n > 16) { // this should never happen
+ n = 16;
+ }
+ for (i = 15; i >= n; --i) {
+ s->buf[i] = s->buf[i-n];
+ }
+ s->bufIdx = n;
+ }
+}
+
+//------------------------------------------------------------------------
+// AES-256 decryption
+//------------------------------------------------------------------------
+
+static void aes256KeyExpansion(DecryptAES256State *s,
+ Guchar *objKey, int objKeyLen) {
+ Guint temp;
+ int i, round;
+
+ //~ this assumes objKeyLen == 32
+
+ for (i = 0; i < 8; ++i) {
+ s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) +
+ (objKey[4*i+2] << 8) + objKey[4*i+3];
+ }
+ for (i = 8; i < 60; ++i) {
+ temp = s->w[i-1];
+ if ((i & 7) == 0) {
+ temp = subWord(rotWord(temp)) ^ rcon[i/8];
+ } else if ((i & 7) == 4) {
+ temp = subWord(temp);
+ }
+ s->w[i] = s->w[i-8] ^ temp;
+ }
+ for (round = 1; round <= 13; ++round) {
+ invMixColumnsW(&s->w[round * 4]);
+ }
+}
+
+static void aes256DecryptBlock(DecryptAES256State *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[14 * 4]);
+
+ // rounds 13-1
+ for (round = 13; round >= 1; --round) {
+ invSubBytes(s->state);
+ invShiftRows(s->state);
+ invMixColumns(s->state);
+ addRoundKey(s->state, &s->w[round * 4]);
+ }
+
+ // round 14
+ 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];
+ if (n < 1 || n > 16) { // this should never happen
+ n = 16;
+ }
for (i = 15; i >= n; --i) {
s->buf[i] = s->buf[i-n];
}
@@ -633,12 +844,17 @@ static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
}
-static void md5(Guchar *msg, int msgLen, Guchar *digest) {
+void md5(Guchar *msg, int msgLen, Guchar *digest) {
Gulong x[16];
Gulong a, b, c, d, aa, bb, cc, dd;
int n64;
int i, j, k;
+ // sanity check
+ if (msgLen < 0) {
+ return;
+ }
+
// compute number of 64-byte blocks
// (length + pad byte (0x80) + 8 bytes for length)
n64 = (msgLen + 1 + 8 + 63) / 64;
@@ -774,3 +990,160 @@ static void md5(Guchar *msg, int msgLen, Guchar *digest) {
digest[14] = (Guchar)((d >>= 8) & 0xff);
digest[15] = (Guchar)((d >>= 8) & 0xff);
}
+
+//------------------------------------------------------------------------
+// SHA-256 hash
+//------------------------------------------------------------------------
+
+static Guint sha256K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static inline Guint rotr(Guint x, Guint n) {
+ return (x >> n) | (x << (32 - n));
+}
+
+static inline Guint sha256Ch(Guint x, Guint y, Guint z) {
+ return (x & y) ^ (~x & z);
+}
+
+static inline Guint sha256Maj(Guint x, Guint y, Guint z) {
+ return (x & y) ^ (x & z) ^ (y & z);
+}
+
+static inline Guint sha256Sigma0(Guint x) {
+ return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
+}
+
+static inline Guint sha256Sigma1(Guint x) {
+ return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
+}
+
+static inline Guint sha256sigma0(Guint x) {
+ return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3);
+}
+
+static inline Guint sha256sigma1(Guint x) {
+ return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10);
+}
+
+void sha256HashBlock(Guchar *blk, Guint *H) {
+ Guint W[64];
+ Guint a, b, c, d, e, f, g, h;
+ Guint T1, T2;
+ Guint t;
+
+ // 1. prepare the message schedule
+ for (t = 0; t < 16; ++t) {
+ W[t] = (blk[t*4] << 24) |
+ (blk[t*4 + 1] << 16) |
+ (blk[t*4 + 2] << 8) |
+ blk[t*4 + 3];
+ }
+ for (t = 16; t < 64; ++t) {
+ W[t] = sha256sigma1(W[t-2]) + W[t-7] + sha256sigma0(W[t-15]) + W[t-16];
+ }
+
+ // 2. initialize the eight working variables
+ a = H[0];
+ b = H[1];
+ c = H[2];
+ d = H[3];
+ e = H[4];
+ f = H[5];
+ g = H[6];
+ h = H[7];
+
+ // 3.
+ for (t = 0; t < 64; ++t) {
+ T1 = h + sha256Sigma1(e) + sha256Ch(e,f,g) + sha256K[t] + W[t];
+ T2 = sha256Sigma0(a) + sha256Maj(a,b,c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ }
+
+ // 4. compute the intermediate hash value
+ H[0] += a;
+ H[1] += b;
+ H[2] += c;
+ H[3] += d;
+ H[4] += e;
+ H[5] += f;
+ H[6] += g;
+ H[7] += h;
+}
+
+static void sha256(Guchar *msg, int msgLen, Guchar *hash) {
+ Guchar blk[64];
+ Guint H[8];
+ int blkLen, i;
+
+ H[0] = 0x6a09e667;
+ H[1] = 0xbb67ae85;
+ H[2] = 0x3c6ef372;
+ H[3] = 0xa54ff53a;
+ H[4] = 0x510e527f;
+ H[5] = 0x9b05688c;
+ H[6] = 0x1f83d9ab;
+ H[7] = 0x5be0cd19;
+
+ blkLen = 0;
+ for (i = 0; i + 64 <= msgLen; i += 64) {
+ sha256HashBlock(msg + i, H);
+ }
+ blkLen = msgLen - i;
+ if (blkLen > 0) {
+ memcpy(blk, msg + i, blkLen);
+ }
+
+ // pad the message
+ blk[blkLen++] = 0x80;
+ if (blkLen > 56) {
+ while (blkLen < 64) {
+ blk[blkLen++] = 0;
+ }
+ sha256HashBlock(blk, H);
+ blkLen = 0;
+ }
+ while (blkLen < 56) {
+ blk[blkLen++] = 0;
+ }
+ blk[56] = 0;
+ blk[57] = 0;
+ blk[58] = 0;
+ blk[59] = 0;
+ blk[60] = (Guchar)(msgLen >> 21);
+ blk[61] = (Guchar)(msgLen >> 13);
+ blk[62] = (Guchar)(msgLen >> 5);
+ blk[63] = (Guchar)(msgLen << 3);
+ sha256HashBlock(blk, H);
+
+ // copy the output into the buffer (convert words to bytes)
+ for (i = 0; i < 8; ++i) {
+ hash[i*4] = (Guchar)(H[i] >> 24);
+ hash[i*4 + 1] = (Guchar)(H[i] >> 16);
+ hash[i*4 + 2] = (Guchar)(H[i] >> 8);
+ hash[i*4 + 3] = (Guchar)H[i];
+ }
+}
diff --git a/xpdf/Decrypt.h b/xpdf/Decrypt.h
index 56f34b7..156acec 100644
--- a/xpdf/Decrypt.h
+++ b/xpdf/Decrypt.h
@@ -34,6 +34,7 @@ public:
// may be NULL, which is treated as an empty string.
static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
+ GString *ownerEnc, GString *userEnc,
int permissions, GString *fileID,
GString *ownerPassword, GString *userPassword,
Guchar *fileKey, GBool encryptMetadata,
@@ -66,6 +67,14 @@ struct DecryptAESState {
int bufIdx;
};
+struct DecryptAES256State {
+ Guint w[60];
+ Guchar state[16];
+ Guchar cbc[16];
+ Guchar buf[16];
+ int bufIdx;
+};
+
class DecryptStream: public FilterStream {
public:
@@ -84,12 +93,19 @@ private:
CryptAlgorithm algo;
int objKeyLength;
- Guchar objKey[16 + 9];
+ Guchar objKey[32];
union {
DecryptRC4State rc4;
DecryptAESState aes;
+ DecryptAES256State aes256;
} state;
};
+//------------------------------------------------------------------------
+
+extern void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
+extern Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
+extern void md5(Guchar *msg, int msgLen, Guchar *digest);
+
#endif
diff --git a/xpdf/Dict.cc b/xpdf/Dict.cc
index dd1517f..3ef804b 100644
--- a/xpdf/Dict.cc
+++ b/xpdf/Dict.cc
@@ -54,7 +54,7 @@ void Dict::add(char *key, Object *val) {
++length;
}
-inline DictEntry *Dict::find(char *key) {
+inline DictEntry *Dict::find(const char *key) {
int i;
for (i = 0; i < length; ++i) {
@@ -64,19 +64,20 @@ inline DictEntry *Dict::find(char *key) {
return NULL;
}
-GBool Dict::is(char *type) {
+GBool Dict::is(const char *type) {
DictEntry *e;
return (e = find("Type")) && e->val.isName(type);
}
-Object *Dict::lookup(char *key, Object *obj) {
+Object *Dict::lookup(const char *key, Object *obj, int recursion) {
DictEntry *e;
- return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
+ return (e = find(key)) ? e->val.fetch(xref, obj, recursion)
+ : obj->initNull();
}
-Object *Dict::lookupNF(char *key, Object *obj) {
+Object *Dict::lookupNF(const char *key, Object *obj) {
DictEntry *e;
return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
diff --git a/xpdf/Dict.h b/xpdf/Dict.h
index 08f55ec..1f3f8b5 100644
--- a/xpdf/Dict.h
+++ b/xpdf/Dict.h
@@ -46,12 +46,12 @@ public:
void add(char *key, Object *val);
// Check if dictionary is of specified type.
- GBool is(char *type);
+ GBool is(const char *type);
// Look up an entry and return the value. Returns a null object
// if <key> is not in the dictionary.
- Object *lookup(char *key, Object *obj);
- Object *lookupNF(char *key, Object *obj);
+ Object *lookup(const char *key, Object *obj, int recursion = 0);
+ Object *lookupNF(const char *key, Object *obj);
// Iterative accessors.
char *getKey(int i);
@@ -71,7 +71,7 @@ private:
int length; // number of entries in dictionary
int ref; // reference count
- DictEntry *find(char *key);
+ DictEntry *find(const char *key);
};
#endif
diff --git a/xpdf/Error.cc b/xpdf/Error.cc
index c03f75f..cb4f27c 100644
--- a/xpdf/Error.cc
+++ b/xpdf/Error.cc
@@ -15,24 +15,54 @@
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
+#include "GString.h"
#include "GlobalParams.h"
#include "Error.h"
-void CDECL error(int pos, char *msg, ...) {
+static const char *errorCategoryNames[] = {
+ "Syntax Warning",
+ "Syntax Error",
+ "Config Error",
+ "Command Line Error",
+ "I/O Error",
+ "Permission Error",
+ "Unimplemented Feature",
+ "Internal Error"
+};
+
+static void (*errorCbk)(void *data, ErrorCategory category,
+ int pos, char *msg) = NULL;
+static void *errorCbkData = NULL;
+
+void setErrorCallback(void (*cbk)(void *data, ErrorCategory category,
+ int pos, char *msg),
+ void *data) {
+ errorCbk = cbk;
+ errorCbkData = data;
+}
+
+void CDECL error(ErrorCategory category, int pos, const char *msg, ...) {
va_list args;
+ GString *s;
// NB: this can be called before the globalParams object is created
- if (globalParams && globalParams->getErrQuiet()) {
+ if (!errorCbk && globalParams && globalParams->getErrQuiet()) {
return;
}
- if (pos >= 0) {
- fprintf(stderr, "Error (%d): ", pos);
- } else {
- fprintf(stderr, "Error: ");
- }
va_start(args, msg);
- vfprintf(stderr, msg, args);
+ s = GString::formatv(msg, args);
va_end(args);
- fprintf(stderr, "\n");
- fflush(stderr);
+ if (errorCbk) {
+ (*errorCbk)(errorCbkData, category, pos, s->getCString());
+ } else {
+ if (pos >= 0) {
+ fprintf(stderr, "%s (%d): %s\n",
+ errorCategoryNames[category], pos, s->getCString());
+ } else {
+ fprintf(stderr, "%s: %s\n",
+ errorCategoryNames[category], s->getCString());
+ }
+ fflush(stderr);
+ }
+ delete s;
}
diff --git a/xpdf/Error.h b/xpdf/Error.h
index 0ce55e9..a4ae5c9 100644
--- a/xpdf/Error.h
+++ b/xpdf/Error.h
@@ -18,6 +18,25 @@
#include <stdio.h>
#include "config.h"
-extern void CDECL error(int pos, char *msg, ...);
+enum ErrorCategory {
+ errSyntaxWarning, // PDF syntax error which can be worked around;
+ // output will probably be correct
+ errSyntaxError, // PDF syntax error which can be worked around;
+ // output will probably be incorrect
+ errConfig, // error in Xpdf config info (xpdfrc file, etc.)
+ errCommandLine, // error in user-supplied parameters, action not
+ // allowed, etc. (only used by command-line tools)
+ errIO, // error in file I/O
+ errNotAllowed, // action not allowed by PDF permission bits
+ errUnimplemented, // unimplemented PDF feature - display will be
+ // incorrect
+ errInternal // internal error - malfunction within the Xpdf code
+};
+
+extern void setErrorCallback(void (*cbk)(void *data, ErrorCategory category,
+ int pos, char *msg),
+ void *data);
+
+extern void CDECL error(ErrorCategory category, int pos, const char *msg, ...);
#endif
diff --git a/xpdf/FontEncodingTables.cc b/xpdf/FontEncodingTables.cc
index f3b9280..bf04b5b 100644
--- a/xpdf/FontEncodingTables.cc
+++ b/xpdf/FontEncodingTables.cc
@@ -10,7 +10,7 @@
#include <stdlib.h>
#include "FontEncodingTables.h"
-char *macRomanEncoding[256] = {
+const char *macRomanEncoding[256] = {
NULL,
NULL,
NULL,
@@ -269,7 +269,7 @@ char *macRomanEncoding[256] = {
"caron"
};
-char *macExpertEncoding[256] = {
+const char *macExpertEncoding[256] = {
NULL,
NULL,
NULL,
@@ -528,7 +528,7 @@ char *macExpertEncoding[256] = {
NULL
};
-char *winAnsiEncoding[256] = {
+const char *winAnsiEncoding[256] = {
NULL,
NULL,
NULL,
@@ -787,7 +787,7 @@ char *winAnsiEncoding[256] = {
"ydieresis"
};
-char *standardEncoding[256] = {
+const char *standardEncoding[256] = {
NULL,
NULL,
NULL,
@@ -1046,7 +1046,7 @@ char *standardEncoding[256] = {
NULL
};
-char *expertEncoding[256] = {
+const char *expertEncoding[256] = {
NULL,
NULL,
NULL,
@@ -1305,7 +1305,7 @@ char *expertEncoding[256] = {
"Ydieresissmall"
};
-char *symbolEncoding[256] = {
+const char *symbolEncoding[256] = {
NULL,
NULL,
NULL,
@@ -1564,7 +1564,7 @@ char *symbolEncoding[256] = {
NULL
};
-char *zapfDingbatsEncoding[256] = {
+const char *zapfDingbatsEncoding[256] = {
NULL,
NULL,
NULL,
diff --git a/xpdf/FontEncodingTables.h b/xpdf/FontEncodingTables.h
index 8b0a1e7..a417b32 100644
--- a/xpdf/FontEncodingTables.h
+++ b/xpdf/FontEncodingTables.h
@@ -9,12 +9,12 @@
#ifndef FONTENCODINGTABLES_H
#define FONTENCODINGTABLES_H
-extern char *macRomanEncoding[];
-extern char *macExpertEncoding[];
-extern char *winAnsiEncoding[];
-extern char *standardEncoding[];
-extern char *expertEncoding[];
-extern char *symbolEncoding[];
-extern char *zapfDingbatsEncoding[];
+extern const char *macRomanEncoding[];
+extern const char *macExpertEncoding[];
+extern const char *winAnsiEncoding[];
+extern const char *standardEncoding[];
+extern const char *expertEncoding[];
+extern const char *symbolEncoding[];
+extern const char *zapfDingbatsEncoding[];
#endif
diff --git a/xpdf/Function.cc b/xpdf/Function.cc
index a4d51c7..2659af1 100644
--- a/xpdf/Function.cc
+++ b/xpdf/Function.cc
@@ -24,6 +24,12 @@
#include "Function.h"
//------------------------------------------------------------------------
+
+// Max depth of nested functions. This is used to catch infinite
+// loops in the function object structure.
+#define recursionLimit 8
+
+//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
@@ -33,12 +39,17 @@ Function::Function() {
Function::~Function() {
}
-Function *Function::parse(Object *funcObj) {
+Function *Function::parse(Object *funcObj, int recursion) {
Function *func;
Dict *dict;
int funcType;
Object obj1;
+ if (recursion > recursionLimit) {
+ error(errSyntaxError, -1, "Loop detected in function objects");
+ return NULL;
+ }
+
if (funcObj->isStream()) {
dict = funcObj->streamGetDict();
} else if (funcObj->isDict()) {
@@ -46,12 +57,12 @@ Function *Function::parse(Object *funcObj) {
} else if (funcObj->isName("Identity")) {
return new IdentityFunction();
} else {
- error(-1, "Expected function dictionary or stream");
+ error(errSyntaxError, -1, "Expected function dictionary or stream");
return NULL;
}
if (!dict->lookup("FunctionType", &obj1)->isInt()) {
- error(-1, "Function type is missing or wrong type");
+ error(errSyntaxError, -1, "Function type is missing or wrong type");
obj1.free();
return NULL;
}
@@ -63,11 +74,11 @@ Function *Function::parse(Object *funcObj) {
} else if (funcType == 2) {
func = new ExponentialFunction(funcObj, dict);
} else if (funcType == 3) {
- func = new StitchingFunction(funcObj, dict);
+ func = new StitchingFunction(funcObj, dict, recursion);
} else if (funcType == 4) {
func = new PostScriptFunction(funcObj, dict);
} else {
- error(-1, "Unimplemented function type (%d)", funcType);
+ error(errSyntaxError, -1, "Unimplemented function type ({0:d})", funcType);
return NULL;
}
if (!func->isOk()) {
@@ -84,26 +95,27 @@ GBool Function::init(Dict *dict) {
//----- Domain
if (!dict->lookup("Domain", &obj1)->isArray()) {
- error(-1, "Function is missing domain");
+ error(errSyntaxError, -1, "Function is missing domain");
goto err2;
}
m = obj1.arrayGetLength() / 2;
if (m > funcMaxInputs) {
- error(-1, "Functions with more than %d inputs are unsupported",
+ error(errSyntaxError, -1,
+ "Functions with more than {0:d} inputs are unsupported",
funcMaxInputs);
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
+ error(errSyntaxError, -1, "Illegal value in function domain array");
goto err1;
}
domain[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
+ error(errSyntaxError, -1, "Illegal value in function domain array");
goto err1;
}
domain[i][1] = obj2.getNum();
@@ -118,21 +130,22 @@ GBool Function::init(Dict *dict) {
hasRange = gTrue;
n = obj1.arrayGetLength() / 2;
if (n > funcMaxOutputs) {
- error(-1, "Functions with more than %d outputs are unsupported",
+ error(errSyntaxError, -1,
+ "Functions with more than {0:d} outputs are unsupported",
funcMaxOutputs);
goto err2;
}
for (i = 0; i < n; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
+ error(errSyntaxError, -1, "Illegal value in function range array");
goto err1;
}
range[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
+ error(errSyntaxError, -1, "Illegal value in function range array");
goto err1;
}
range[i][1] = obj2.getNum();
@@ -191,8 +204,10 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
Guint buf, bitMask;
int bits;
Guint s;
- int i;
+ double in[funcMaxInputs];
+ int i, j, t, bit, idx;
+ idxOffset = NULL;
samples = NULL;
sBuf = NULL;
ok = gFalse;
@@ -202,11 +217,12 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
goto err1;
}
if (!hasRange) {
- error(-1, "Type 0 function is missing range");
+ error(errSyntaxError, -1, "Type 0 function is missing range");
goto err1;
}
if (m > sampledFuncMaxInputs) {
- error(-1, "Sampled functions with more than %d inputs are unsupported",
+ error(errSyntaxError, -1,
+ "Sampled functions with more than {0:d} inputs are unsupported",
sampledFuncMaxInputs);
goto err1;
}
@@ -216,7 +232,7 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
//----- get the stream
if (!funcObj->isStream()) {
- error(-1, "Type 0 function isn't a stream");
+ error(errSyntaxError, -1, "Type 0 function isn't a stream");
goto err1;
}
str = funcObj->getStream();
@@ -224,27 +240,45 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
//----- Size
if (!dict->lookup("Size", &obj1)->isArray() ||
obj1.arrayGetLength() != m) {
- error(-1, "Function has missing or invalid size array");
+ error(errSyntaxError, -1, "Function has missing or invalid size array");
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isInt()) {
- error(-1, "Illegal value in function size array");
+ error(errSyntaxError, -1, "Illegal value in function size array");
goto err3;
}
sampleSize[i] = obj2.getInt();
+ if (sampleSize[i] <= 0) {
+ error(errSyntaxError, -1, "Illegal non-positive value in function size array");
+ goto err3;
+ }
obj2.free();
}
obj1.free();
- idxMul[0] = n;
- for (i = 1; i < m; ++i) {
- idxMul[i] = idxMul[i-1] * sampleSize[i-1];
+ idxOffset = (int *)gmallocn(1 << m, sizeof(int));
+ for (i = 0; i < (1<<m); ++i) {
+ idx = 0;
+ for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
+ if (sampleSize[j] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idx = (idx + bit) * sampleSize[j-1];
+ }
+ if (sampleSize[0] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idxOffset[i] = (idx + bit) * n;
}
//----- BitsPerSample
if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
- error(-1, "Function has missing or invalid BitsPerSample");
+ error(errSyntaxError, -1, "Function has missing or invalid BitsPerSample");
goto err2;
}
sampleBits = obj1.getInt();
@@ -257,14 +291,14 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
for (i = 0; i < m; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
+ error(errSyntaxError, -1, "Illegal value in function encode array");
goto err3;
}
encode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
+ error(errSyntaxError, -1, "Illegal value in function encode array");
goto err3;
}
encode[i][1] = obj2.getNum();
@@ -288,14 +322,14 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
for (i = 0; i < n; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
+ error(errSyntaxError, -1, "Illegal value in function decode array");
goto err3;
}
decode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
+ error(errSyntaxError, -1, "Illegal value in function decode array");
goto err3;
}
decode[i][1] = obj2.getNum();
@@ -341,6 +375,13 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
}
str->close();
+ // set up the cache
+ for (i = 0; i < m; ++i) {
+ in[i] = domain[i][0];
+ cacheIn[i] = in[i] - 1;
+ }
+ transform(in, cacheOut);
+
ok = gTrue;
return;
@@ -353,6 +394,9 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
}
SampledFunction::~SampledFunction() {
+ if (idxOffset) {
+ gfree(idxOffset);
+ }
if (samples) {
gfree(samples);
}
@@ -363,6 +407,8 @@ SampledFunction::~SampledFunction() {
SampledFunction::SampledFunction(SampledFunction *func) {
memcpy(this, func, sizeof(SampledFunction));
+ idxOffset = (int *)gmallocn(1 << m, sizeof(int));
+ memcpy(idxOffset, func->idxOffset, (1 << m) * (int)sizeof(int));
samples = (double *)gmallocn(nSamples, sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
sBuf = (double *)gmallocn(1 << m, sizeof(double));
@@ -370,38 +416,54 @@ SampledFunction::SampledFunction(SampledFunction *func) {
void SampledFunction::transform(double *in, double *out) {
double x;
- int e[funcMaxInputs][2];
+ int e[funcMaxInputs];
double efrac0[funcMaxInputs];
double efrac1[funcMaxInputs];
- int i, j, k, idx, t;
+ int i, j, k, idx0, t;
+
+ // check the cache
+ for (i = 0; i < m; ++i) {
+ if (in[i] != cacheIn[i]) {
+ break;
+ }
+ }
+ if (i == m) {
+ for (i = 0; i < n; ++i) {
+ out[i] = cacheOut[i];
+ }
+ return;
+ }
// map input values into sample array
for (i = 0; i < m; ++i) {
x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
- if (x < 0) {
+ if (x < 0 || x != x) { // x!=x is a more portable version of isnan(x)
x = 0;
} else if (x > sampleSize[i] - 1) {
x = sampleSize[i] - 1;
}
- e[i][0] = (int)x;
- if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) {
+ e[i] = (int)x;
+ if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) {
// this happens if in[i] = domain[i][1]
- e[i][1] = e[i][0];
+ e[i] = sampleSize[i] - 2;
}
- efrac1[i] = x - e[i][0];
+ efrac1[i] = x - e[i];
efrac0[i] = 1 - efrac1[i];
}
+ // compute index for the first sample to be used
+ idx0 = 0;
+ for (k = m - 1; k >= 1; --k) {
+ idx0 = (idx0 + e[k]) * sampleSize[k-1];
+ }
+ idx0 = (idx0 + e[0]) * n;
+
// for each output, do m-linear interpolation
for (i = 0; i < n; ++i) {
// pull 2^m values out of the sample array
for (j = 0; j < (1<<m); ++j) {
- idx = i;
- for (k = 0, t = j; k < m; ++k, t >>= 1) {
- idx += idxMul[k] * (e[k][t & 1]);
- }
- sBuf[j] = samples[idx];
+ sBuf[j] = samples[idx0 + idxOffset[j] + i];
}
// do m sets of interpolations
@@ -419,6 +481,14 @@ void SampledFunction::transform(double *in, double *out) {
out[i] = range[i][1];
}
}
+
+ // save current result in the cache
+ for (i = 0; i < m; ++i) {
+ cacheIn[i] = in[i];
+ }
+ for (i = 0; i < n; ++i) {
+ cacheOut[i] = out[i];
+ }
}
//------------------------------------------------------------------------
@@ -436,21 +506,21 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
goto err1;
}
if (m != 1) {
- error(-1, "Exponential function with more than one input");
+ error(errSyntaxError, -1, "Exponential function with more than one input");
goto err1;
}
//----- C0
if (dict->lookup("C0", &obj1)->isArray()) {
if (hasRange && obj1.arrayGetLength() != n) {
- error(-1, "Function's C0 array is wrong length");
+ error(errSyntaxError, -1, "Function's C0 array is wrong length");
goto err2;
}
n = obj1.arrayGetLength();
for (i = 0; i < n; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function C0 array");
+ error(errSyntaxError, -1, "Illegal value in function C0 array");
goto err3;
}
c0[i] = obj2.getNum();
@@ -458,7 +528,7 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
}
} else {
if (hasRange && n != 1) {
- error(-1, "Function's C0 array is wrong length");
+ error(errSyntaxError, -1, "Function's C0 array is wrong length");
goto err2;
}
n = 1;
@@ -469,13 +539,13 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
//----- C1
if (dict->lookup("C1", &obj1)->isArray()) {
if (obj1.arrayGetLength() != n) {
- error(-1, "Function's C1 array is wrong length");
+ error(errSyntaxError, -1, "Function's C1 array is wrong length");
goto err2;
}
for (i = 0; i < n; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isNum()) {
- error(-1, "Illegal value in function C1 array");
+ error(errSyntaxError, -1, "Illegal value in function C1 array");
goto err3;
}
c1[i] = obj2.getNum();
@@ -483,7 +553,7 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
}
} else {
if (n != 1) {
- error(-1, "Function's C1 array is wrong length");
+ error(errSyntaxError, -1, "Function's C1 array is wrong length");
goto err2;
}
c1[0] = 1;
@@ -492,7 +562,7 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
//----- N (exponent)
if (!dict->lookup("N", &obj1)->isNum()) {
- error(-1, "Function has missing or invalid N");
+ error(errSyntaxError, -1, "Function has missing or invalid N");
goto err2;
}
e = obj1.getNum();
@@ -544,7 +614,8 @@ void ExponentialFunction::transform(double *in, double *out) {
// StitchingFunction
//------------------------------------------------------------------------
-StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
+StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
+ int recursion) {
Object obj1, obj2;
int i;
@@ -559,13 +630,14 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
goto err1;
}
if (m != 1) {
- error(-1, "Stitching function with more than one input");
+ error(errSyntaxError, -1, "Stitching function with more than one input");
goto err1;
}
//----- Functions
if (!dict->lookup("Functions", &obj1)->isArray()) {
- error(-1, "Missing 'Functions' entry in stitching function");
+ error(errSyntaxError, -1,
+ "Missing 'Functions' entry in stitching function");
goto err1;
}
k = obj1.arrayGetLength();
@@ -577,12 +649,14 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
funcs[i] = NULL;
}
for (i = 0; i < k; ++i) {
- if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
+ if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2),
+ recursion + 1))) {
goto err2;
}
- if (i > 0 && (funcs[i]->getInputSize() != 1 ||
- funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
- error(-1, "Incompatible subfunctions in stitching function");
+ if (funcs[i]->getInputSize() != 1 ||
+ (i > 0 && funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
+ error(errSyntaxError, -1,
+ "Incompatible subfunctions in stitching function");
goto err2;
}
obj2.free();
@@ -592,13 +666,15 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
//----- Bounds
if (!dict->lookup("Bounds", &obj1)->isArray() ||
obj1.arrayGetLength() != k - 1) {
- error(-1, "Missing or invalid 'Bounds' entry in stitching function");
+ error(errSyntaxError, -1,
+ "Missing or invalid 'Bounds' entry in stitching function");
goto err1;
}
bounds[0] = domain[0][0];
for (i = 1; i < k; ++i) {
if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
- error(-1, "Invalid type in 'Bounds' array in stitching function");
+ error(errSyntaxError, -1,
+ "Invalid type in 'Bounds' array in stitching function");
goto err2;
}
bounds[i] = obj2.getNum();
@@ -610,12 +686,14 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
//----- Encode
if (!dict->lookup("Encode", &obj1)->isArray() ||
obj1.arrayGetLength() != 2 * k) {
- error(-1, "Missing or invalid 'Encode' entry in stitching function");
+ error(errSyntaxError, -1,
+ "Missing or invalid 'Encode' entry in stitching function");
goto err1;
}
for (i = 0; i < 2 * k; ++i) {
if (!obj1.arrayGet(i, &obj2)->isNum()) {
- error(-1, "Invalid type in 'Encode' array in stitching function");
+ error(errSyntaxError, -1,
+ "Invalid type in 'Encode' array in stitching function");
goto err2;
}
encode[i] = obj2.getNum();
@@ -646,7 +724,7 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
StitchingFunction::StitchingFunction(StitchingFunction *func) {
int i;
- k = func->k;
+ memcpy(this, func, sizeof(StitchingFunction));
funcs = (Function **)gmallocn(k, sizeof(Function *));
for (i = 0; i < k; ++i) {
funcs[i] = func->funcs[i]->copy();
@@ -749,7 +827,7 @@ enum PSOp {
// Note: 'if' and 'ifelse' are parsed separately.
// The rest are listed here in alphabetical order.
// The index in this table is equivalent to the entry in PSOp.
-char *psOpNames[] = {
+static const char *psOpNames[] = {
"abs",
"add",
"and",
@@ -875,7 +953,7 @@ private:
GBool PSStack::checkOverflow(int n) {
if (sp - n < 0) {
- error(-1, "Stack overflow in PostScript function");
+ error(errSyntaxError, -1, "Stack overflow in PostScript function");
return gFalse;
}
return gTrue;
@@ -883,7 +961,7 @@ GBool PSStack::checkOverflow(int n) {
GBool PSStack::checkUnderflow() {
if (sp == psStackSize) {
- error(-1, "Stack underflow in PostScript function");
+ error(errSyntaxError, -1, "Stack underflow in PostScript function");
return gFalse;
}
return gTrue;
@@ -891,7 +969,7 @@ GBool PSStack::checkUnderflow() {
GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
if (stack[sp].type != t1 && stack[sp].type != t2) {
- error(-1, "Type mismatch in PostScript function");
+ error(errSyntaxError, -1, "Type mismatch in PostScript function");
return gFalse;
}
return gTrue;
@@ -947,7 +1025,7 @@ void PSStack::copy(int n) {
int i;
if (sp + n > psStackSize) {
- error(-1, "Stack underflow in PostScript function");
+ error(errSyntaxError, -1, "Stack underflow in PostScript function");
return;
}
if (!checkOverflow(n)) {
@@ -971,7 +1049,7 @@ void PSStack::roll(int n, int j) {
j = n - j;
}
}
- if (n <= 0 || j == 0) {
+ if (n <= 0 || j == 0 || n > psStackSize || sp + n > psStackSize) {
return;
}
for (i = 0; i < j; ++i) {
@@ -1002,7 +1080,10 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
Stream *str;
int codePtr;
GString *tok;
+ double in[funcMaxInputs];
+ int i;
+ codeString = NULL;
code = NULL;
codeSize = 0;
ok = gFalse;
@@ -1012,13 +1093,13 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
goto err1;
}
if (!hasRange) {
- error(-1, "Type 4 function is missing range");
+ error(errSyntaxError, -1, "Type 4 function is missing range");
goto err1;
}
//----- get the stream
if (!funcObj->isStream()) {
- error(-1, "Type 4 function isn't a stream");
+ error(errSyntaxError, -1, "Type 4 function isn't a stream");
goto err1;
}
str = funcObj->getStream();
@@ -1027,7 +1108,7 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
codeString = new GString();
str->reset();
if (!(tok = getToken(str)) || tok->cmp("{")) {
- error(-1, "Expected '{' at start of PostScript function");
+ error(errSyntaxError, -1, "Expected '{' at start of PostScript function");
if (tok) {
delete tok;
}
@@ -1040,6 +1121,13 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
}
str->close();
+ //----- set up the cache
+ for (i = 0; i < m; ++i) {
+ in[i] = domain[i][0];
+ cacheIn[i] = in[i] - 1;
+ }
+ transform(in, cacheOut);
+
ok = gTrue;
err2:
@@ -1057,13 +1145,28 @@ PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
PostScriptFunction::~PostScriptFunction() {
gfree(code);
- delete codeString;
+ if (codeString) {
+ delete codeString;
+ }
}
void PostScriptFunction::transform(double *in, double *out) {
PSStack *stack;
int i;
+ // check the cache
+ for (i = 0; i < m; ++i) {
+ if (in[i] != cacheIn[i]) {
+ break;
+ }
+ }
+ if (i == m) {
+ for (i = 0; i < n; ++i) {
+ out[i] = cacheOut[i];
+ }
+ return;
+ }
+
stack = new PSStack();
for (i = 0; i < m; ++i) {
//~ may need to check for integers here
@@ -1079,9 +1182,18 @@ void PostScriptFunction::transform(double *in, double *out) {
}
}
// if (!stack->empty()) {
- // error(-1, "Extra values on stack at end of PostScript function");
+ // error(errSyntaxWarning, -1,
+ // "Extra values on stack at end of PostScript function");
// }
delete stack;
+
+ // save current result in the cache
+ for (i = 0; i < m; ++i) {
+ cacheIn[i] = in[i];
+ }
+ for (i = 0; i < n; ++i) {
+ cacheOut[i] = out[i];
+ }
}
GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
@@ -1093,13 +1205,14 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
while (1) {
if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
+ error(errSyntaxError, -1,
+ "Unexpected end of PostScript function stream");
return gFalse;
}
p = tok->getCString();
if (isdigit(*p) || *p == '.' || *p == '-') {
isReal = gFalse;
- for (++p; *p; ++p) {
+ for (; *p; ++p) {
if (*p == '.') {
isReal = gTrue;
break;
@@ -1124,7 +1237,8 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
return gFalse;
}
if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
+ error(errSyntaxError, -1,
+ "Unexpected end of PostScript function stream");
return gFalse;
}
if (!tok->cmp("{")) {
@@ -1134,7 +1248,8 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
}
delete tok;
if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
+ error(errSyntaxError, -1,
+ "Unexpected end of PostScript function stream");
return gFalse;
}
} else {
@@ -1142,7 +1257,8 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
}
if (!tok->cmp("if")) {
if (elsePtr >= 0) {
- error(-1, "Got 'if' operator with two blocks in PostScript function");
+ error(errSyntaxError, -1,
+ "Got 'if' operator with two blocks in PostScript function");
return gFalse;
}
code[opPtr].type = psOperator;
@@ -1151,7 +1267,8 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
code[opPtr+2].blk = *codePtr;
} else if (!tok->cmp("ifelse")) {
if (elsePtr < 0) {
- error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
+ error(errSyntaxError, -1,
+ "Got 'ifelse' operator with one block in PostScript function");
return gFalse;
}
code[opPtr].type = psOperator;
@@ -1161,7 +1278,8 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
code[opPtr+2].type = psBlock;
code[opPtr+2].blk = *codePtr;
} else {
- error(-1, "Expected if/ifelse operator in PostScript function");
+ error(errSyntaxError, -1,
+ "Expected if/ifelse operator in PostScript function");
delete tok;
return gFalse;
}
@@ -1176,6 +1294,7 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
} else {
a = -1;
b = nPSOps;
+ cmp = 0; // make gcc happy
// invariant: psOpNames[a] < tok < psOpNames[b]
while (b - a > 1) {
mid = (a + b) / 2;
@@ -1189,8 +1308,9 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
}
}
if (cmp != 0) {
- error(-1, "Unknown operator '%s' in PostScript function",
- tok->getCString());
+ error(errSyntaxError, -1,
+ "Unknown operator '{0:t}' in PostScript function",
+ tok);
delete tok;
return gFalse;
}
@@ -1314,7 +1434,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
if (i2 > 0) {
stack->pushInt(i1 << i2);
} else if (i2 < 0) {
- stack->pushInt((int)((Guint)i1 >> i2));
+ stack->pushInt((int)((Guint)i1 >> -i2));
} else {
stack->pushInt(i1);
}
@@ -1566,7 +1686,8 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
}
break;
default:
- error(-1, "Internal: bad object in PostScript function code");
+ error(errSyntaxError, -1,
+ "Internal: bad object in PostScript function code");
break;
}
}
diff --git a/xpdf/Function.h b/xpdf/Function.h
index 334a439..8852dca 100644
--- a/xpdf/Function.h
+++ b/xpdf/Function.h
@@ -39,7 +39,7 @@ public:
virtual ~Function();
// Construct a function. Returns NULL if unsuccessful.
- static Function *parse(Object *funcObj);
+ static Function *parse(Object *funcObj, int recursion = 0);
// Initialize the entries common to all function types.
GBool init(Dict *dict);
@@ -129,10 +129,12 @@ private:
decode[funcMaxOutputs][2];
double // input multipliers
inputMul[funcMaxInputs];
- int idxMul[funcMaxInputs]; // sample array index multipliers
+ int *idxOffset;
double *samples; // the samples
int nSamples; // size of the samples array
double *sBuf; // buffer for the transform function
+ double cacheIn[funcMaxInputs];
+ double cacheOut[funcMaxOutputs];
GBool ok;
};
@@ -171,7 +173,7 @@ private:
class StitchingFunction: public Function {
public:
- StitchingFunction(Object *funcObj, Dict *dict);
+ StitchingFunction(Object *funcObj, Dict *dict, int recursion);
virtual ~StitchingFunction();
virtual Function *copy() { return new StitchingFunction(this); }
virtual int getType() { return 3; }
@@ -223,6 +225,8 @@ private:
GString *codeString;
PSObject *code;
int codeSize;
+ double cacheIn[funcMaxInputs];
+ double cacheOut[funcMaxOutputs];
GBool ok;
};
diff --git a/xpdf/Gfx.cc b/xpdf/Gfx.cc
index b7655b6..1979f84 100644
--- a/xpdf/Gfx.cc
+++ b/xpdf/Gfx.cc
@@ -18,9 +18,12 @@
#include <string.h>
#include <math.h>
#include "gmem.h"
+#include "GString.h"
+#include "GList.h"
#include "GlobalParams.h"
#include "CharTypes.h"
#include "Object.h"
+#include "PDFDoc.h"
#include "Array.h"
#include "Dict.h"
#include "Stream.h"
@@ -31,7 +34,9 @@
#include "OutputDev.h"
#include "Page.h"
#include "Annot.h"
+#include "OptionalContent.h"
#include "Error.h"
+#include "PDFDocEncoding.h"
#include "Gfx.h"
// the MSVC math.h doesn't define this
@@ -298,6 +303,9 @@ GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
// get graphics state parameter dictionary
resDict->lookup("ExtGState", &gStateDict);
+ // get properties dictionary
+ resDict->lookup("Properties", &propsDict);
+
} else {
fonts = NULL;
xObjDict.initNull();
@@ -305,6 +313,7 @@ GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
patternDict.initNull();
shadingDict.initNull();
gStateDict.initNull();
+ propsDict.initNull();
}
next = nextA;
@@ -319,6 +328,7 @@ GfxResources::~GfxResources() {
patternDict.free();
shadingDict.free();
gStateDict.free();
+ propsDict.free();
}
GfxFont *GfxResources::lookupFont(char *name) {
@@ -331,7 +341,7 @@ GfxFont *GfxResources::lookupFont(char *name) {
return font;
}
}
- error(-1, "Unknown font tag '%s'", name);
+ error(errSyntaxError, -1, "Unknown font tag '{0:s}'", name);
return NULL;
}
@@ -345,7 +355,7 @@ GBool GfxResources::lookupXObject(char *name, Object *obj) {
obj->free();
}
}
- error(-1, "XObject '%s' is unknown", name);
+ error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name);
return gFalse;
}
@@ -359,7 +369,7 @@ GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
obj->free();
}
}
- error(-1, "XObject '%s' is unknown", name);
+ error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name);
return gFalse;
}
@@ -392,7 +402,7 @@ GfxPattern *GfxResources::lookupPattern(char *name) {
obj.free();
}
}
- error(-1, "Unknown pattern '%s'", name);
+ error(errSyntaxError, -1, "Unknown pattern '{0:s}'", name);
return NULL;
}
@@ -411,7 +421,7 @@ GfxShading *GfxResources::lookupShading(char *name) {
obj.free();
}
}
- error(-1, "Unknown shading '%s'", name);
+ error(errSyntaxError, -1, "Unknown shading '{0:s}'", name);
return NULL;
}
@@ -426,7 +436,22 @@ GBool GfxResources::lookupGState(char *name, Object *obj) {
obj->free();
}
}
- error(-1, "ExtGState '%s' is unknown", name);
+ error(errSyntaxError, -1, "ExtGState '{0:s}' is unknown", name);
+ return gFalse;
+}
+
+GBool GfxResources::lookupPropertiesNF(char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->propsDict.isDict()) {
+ if (!resPtr->propsDict.dictLookupNF(name, obj)->isNull()) {
+ return gTrue;
+ }
+ obj->free();
+ }
+ }
+ error(errSyntaxError, -1, "Properties '{0:s}' is unknown", name);
return gFalse;
}
@@ -434,14 +459,15 @@ GBool GfxResources::lookupGState(char *name, Object *obj) {
// Gfx
//------------------------------------------------------------------------
-Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
double hDPI, double vDPI, PDFRectangle *box,
PDFRectangle *cropBox, int rotate,
GBool (*abortCheckCbkA)(void *data),
void *abortCheckCbkDataA) {
int i;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
subPage = gFalse;
printCommands = globalParams->getPrintCommands();
@@ -461,6 +487,10 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
baseMatrix[i] = state->getCTM()[i];
}
formDepth = 0;
+ textClipBBoxEmpty = gTrue;
+ markedContentStack = new GList();
+ ocState = gTrue;
+ parser = NULL;
abortCheckCbk = abortCheckCbkA;
abortCheckCbkData = abortCheckCbkDataA;
@@ -477,13 +507,14 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
}
}
-Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
PDFRectangle *box, PDFRectangle *cropBox,
GBool (*abortCheckCbkA)(void *data),
void *abortCheckCbkDataA) {
int i;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
subPage = gTrue;
printCommands = globalParams->getPrintCommands();
@@ -500,6 +531,10 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
baseMatrix[i] = state->getCTM()[i];
}
formDepth = 0;
+ textClipBBoxEmpty = gTrue;
+ markedContentStack = new GList();
+ ocState = gTrue;
+ parser = NULL;
abortCheckCbk = abortCheckCbkA;
abortCheckCbkData = abortCheckCbkDataA;
@@ -517,18 +552,17 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
}
Gfx::~Gfx() {
- while (state->hasSaves()) {
- restoreState();
- }
if (!subPage) {
out->endPage();
}
+ while (state->hasSaves()) {
+ restoreState();
+ }
+ delete state;
while (res) {
popResources();
}
- if (state) {
- delete state;
- }
+ deleteGList(markedContentStack, GfxMarkedContent);
}
void Gfx::display(Object *obj, GBool topLevel) {
@@ -539,14 +573,14 @@ void Gfx::display(Object *obj, GBool topLevel) {
for (i = 0; i < obj->arrayGetLength(); ++i) {
obj->arrayGet(i, &obj2);
if (!obj2.isStream()) {
- error(-1, "Weird page contents");
+ error(errSyntaxError, -1, "Weird page contents");
obj2.free();
return;
}
obj2.free();
}
} else if (!obj->isStream()) {
- error(-1, "Weird page contents");
+ error(errSyntaxError, -1, "Weird page contents");
return;
}
parser = new Parser(xref, new Lexer(xref, obj), gFalse);
@@ -562,7 +596,8 @@ void Gfx::go(GBool topLevel) {
int lastAbortCheck;
// scan a sequence of objects
- updateLevel = lastAbortCheck = 0;
+ updateLevel = 1; // make sure even empty pages trigger a call to dump()
+ lastAbortCheck = 0;
numArgs = 0;
parser->getObj(&obj);
while (!obj.isEOF()) {
@@ -606,7 +641,7 @@ void Gfx::go(GBool topLevel) {
// too many arguments - something is wrong
} else {
- error(getPos(), "Too many args in content stream");
+ error(errSyntaxError, getPos(), "Too many args in content stream");
if (printCommands) {
printf("throwing away arg: ");
obj.print(stdout);
@@ -623,7 +658,7 @@ void Gfx::go(GBool topLevel) {
// args at end with no command
if (numArgs > 0) {
- error(getPos(), "Leftover args in content stream");
+ error(errSyntaxError, getPos(), "Leftover args in content stream");
if (printCommands) {
printf("%d leftovers:", numArgs);
for (i = 0; i < numArgs; ++i) {
@@ -653,7 +688,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
name = cmd->getCmd();
if (!(op = findOp(name))) {
if (ignoreUndef == 0)
- error(getPos(), "Unknown operator '%s'", name);
+ error(errSyntaxError, getPos(), "Unknown operator '{0:s}'", name);
return;
}
@@ -661,26 +696,30 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
argPtr = args;
if (op->numArgs >= 0) {
if (numArgs < op->numArgs) {
- error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
+ error(errSyntaxError, getPos(),
+ "Too few ({0:d}) args to '{1:s}' operator", numArgs, name);
return;
}
if (numArgs > op->numArgs) {
#if 0
- error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name);
+ error(errSyntaxWarning, getPos(),
+ "Too many ({0:d}) args to '{1:s}' operator", numArgs, name);
#endif
argPtr += numArgs - op->numArgs;
numArgs = op->numArgs;
}
} else {
if (numArgs > -op->numArgs) {
- error(getPos(), "Too many (%d) args to '%s' operator",
+ error(errSyntaxError, getPos(),
+ "Too many ({0:d}) args to '{1:s}' operator",
numArgs, name);
return;
}
}
for (i = 0; i < numArgs; ++i) {
if (!checkArg(&argPtr[i], op->tchk[i])) {
- error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
+ error(errSyntaxError, getPos(),
+ "Arg #{0:d} to '{1:s}' operator is wrong type ({2:s})",
i, name, argPtr[i].getTypeName());
return;
}
@@ -695,6 +734,7 @@ Operator *Gfx::findOp(char *name) {
a = -1;
b = numOps;
+ cmp = 0; // make gcc happy
// invariant: opTab[a] < name < opTab[b]
while (b - a > 1) {
m = (a + b) / 2;
@@ -801,6 +841,7 @@ void Gfx::opSetLineWidth(Object args[], int numArgs) {
void Gfx::opSetExtGState(Object args[], int numArgs) {
Object obj1, obj2, obj3, obj4, obj5;
+ Object args2[2];
GfxBlendMode mode;
GBool haveFillOP;
Function *funcs[4];
@@ -808,13 +849,15 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
GBool haveBackdropColor;
GfxColorSpace *blendingColorSpace;
GBool alpha, isolated, knockout;
+ double opac;
int i;
if (!res->lookupGState(args[0].getName(), &obj1)) {
return;
}
if (!obj1.isDict()) {
- error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
+ error(errSyntaxError, getPos(),
+ "ExtGState '{0:s}' is wrong type", args[0].getName());
obj1.free();
return;
}
@@ -824,28 +867,77 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
printf("\n");
}
+ // parameters that are also set by individual PDF operators
+ if (obj1.dictLookup("LW", &obj2)->isNum()) {
+ opSetLineWidth(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("LC", &obj2)->isInt()) {
+ opSetLineCap(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("LJ", &obj2)->isInt()) {
+ opSetLineJoin(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("ML", &obj2)->isNum()) {
+ opSetMiterLimit(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("D", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2) {
+ obj2.arrayGet(0, &args2[0]);
+ obj2.arrayGet(1, &args2[1]);
+ if (args2[0].isArray() && args2[1].isNum()) {
+ opSetDash(args2, 2);
+ }
+ args2[0].free();
+ args2[1].free();
+ }
+ obj2.free();
+#if 0 //~ need to add a new version of GfxResources::lookupFont() that
+ //~ takes an indirect ref instead of a name
+ if (obj1.dictLookup("Font", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2) {
+ obj2.arrayGet(0, &args2[0]);
+ obj2.arrayGet(1, &args2[1]);
+ if (args2[0].isDict() && args2[1].isNum()) {
+ opSetFont(args2, 2);
+ }
+ args2[0].free();
+ args2[1].free();
+ }
+ obj2.free();
+#endif
+ if (obj1.dictLookup("FL", &obj2)->isNum()) {
+ opSetFlat(&obj2, 1);
+ }
+ obj2.free();
+
// transparency support: blend mode, fill/stroke opacity
if (!obj1.dictLookup("BM", &obj2)->isNull()) {
if (state->parseBlendMode(&obj2, &mode)) {
state->setBlendMode(mode);
out->updateBlendMode(state);
} else {
- error(getPos(), "Invalid blend mode in ExtGState");
+ error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState");
}
}
obj2.free();
if (obj1.dictLookup("ca", &obj2)->isNum()) {
- state->setFillOpacity(obj2.getNum());
+ opac = obj2.getNum();
+ state->setFillOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac);
out->updateFillOpacity(state);
}
obj2.free();
if (obj1.dictLookup("CA", &obj2)->isNum()) {
- state->setStrokeOpacity(obj2.getNum());
+ opac = obj2.getNum();
+ state->setStrokeOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac);
out->updateStrokeOpacity(state);
}
obj2.free();
- // fill/stroke overprint
+ // fill/stroke overprint, overprint mode
if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) {
state->setFillOverprint(obj2.getBool());
out->updateFillOverprint(state);
@@ -860,6 +952,11 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
}
}
obj2.free();
+ if (obj1.dictLookup("OPM", &obj2)->isInt()) {
+ state->setOverprintMode(obj2.getInt());
+ out->updateOverprintMode(state);
+ }
+ obj2.free();
// stroke adjust
if (obj1.dictLookup("SA", &obj2)->isBool()) {
@@ -898,7 +995,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
out->updateTransfer(state);
}
} else if (!obj2.isNull()) {
- error(getPos(), "Invalid transfer function in ExtGState");
+ error(errSyntaxError, getPos(), "Invalid transfer function in ExtGState");
}
obj2.free();
@@ -915,13 +1012,18 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
obj3.free();
funcs[0] = NULL;
if (!obj2.dictLookup("TR", &obj3)->isNull()) {
- funcs[0] = Function::parse(&obj3);
- if (funcs[0]->getInputSize() != 1 ||
- funcs[0]->getOutputSize() != 1) {
- error(getPos(),
- "Invalid transfer function in soft mask in ExtGState");
- delete funcs[0];
+ if (obj3.isName("Default") ||
+ obj3.isName("Identity")) {
funcs[0] = NULL;
+ } else {
+ funcs[0] = Function::parse(&obj3);
+ if (funcs[0]->getInputSize() != 1 ||
+ funcs[0]->getOutputSize() != 1) {
+ error(errSyntaxError, getPos(),
+ "Invalid transfer function in soft mask in ExtGState");
+ delete funcs[0];
+ funcs[0] = NULL;
+ }
}
}
obj3.free();
@@ -970,15 +1072,17 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
delete funcs[0];
}
} else {
- error(getPos(), "Invalid soft mask in ExtGState - missing group");
+ error(errSyntaxError, getPos(),
+ "Invalid soft mask in ExtGState - missing group");
}
obj4.free();
} else {
- error(getPos(), "Invalid soft mask in ExtGState - missing group");
+ error(errSyntaxError, getPos(),
+ "Invalid soft mask in ExtGState - missing group");
}
obj3.free();
} else if (!obj2.isNull()) {
- error(getPos(), "Invalid soft mask in ExtGState");
+ error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState");
}
}
obj2.free();
@@ -1006,7 +1110,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha,
// check form type
dict->lookup("FormType", &obj1);
if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(getPos(), "Unknown form type");
+ error(errSyntaxError, getPos(), "Unknown form type");
}
obj1.free();
@@ -1014,7 +1118,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha,
dict->lookup("BBox", &obj1);
if (!obj1.isArray()) {
obj1.free();
- error(getPos(), "Bad form bounding box");
+ error(errSyntaxError, getPos(), "Bad form bounding box");
return;
}
for (i = 0; i < 4; ++i) {
@@ -1045,9 +1149,9 @@ void Gfx::doSoftMask(Object *str, GBool alpha,
// draw it
++formDepth;
- doForm1(str, resDict, m, bbox, gTrue, gTrue,
- blendingColorSpace, isolated, knockout,
- alpha, transferFunc, backdropColor);
+ drawForm(str, resDict, m, bbox, gTrue, gTrue,
+ blendingColorSpace, isolated, knockout,
+ alpha, transferFunc, backdropColor);
--formDepth;
if (blendingColorSpace) {
@@ -1161,7 +1265,7 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
state->setFillColor(&color);
out->updateFillColor(state);
} else {
- error(getPos(), "Bad color space (fill)");
+ error(errSyntaxError, getPos(), "Bad color space (fill)");
}
}
@@ -1185,7 +1289,7 @@ void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
state->setStrokeColor(&color);
out->updateStrokeColor(state);
} else {
- error(getPos(), "Bad color space (stroke)");
+ error(errSyntaxError, getPos(), "Bad color space (stroke)");
}
}
@@ -1194,7 +1298,8 @@ void Gfx::opSetFillColor(Object args[], int numArgs) {
int i;
if (numArgs != state->getFillColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'sc' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'sc' command");
return;
}
state->setFillPattern(NULL);
@@ -1210,7 +1315,8 @@ void Gfx::opSetStrokeColor(Object args[], int numArgs) {
int i;
if (numArgs != state->getStrokeColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SC' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'SC' command");
return;
}
state->setStrokePattern(NULL);
@@ -1231,7 +1337,8 @@ void Gfx::opSetFillColorN(Object args[], int numArgs) {
if (!((GfxPatternColorSpace *)state->getFillColorSpace())->getUnder() ||
numArgs - 1 != ((GfxPatternColorSpace *)state->getFillColorSpace())
->getUnder()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'scn' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'scn' command");
return;
}
for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) {
@@ -1249,7 +1356,8 @@ void Gfx::opSetFillColorN(Object args[], int numArgs) {
} else {
if (numArgs != state->getFillColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'scn' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'scn' command");
return;
}
state->setFillPattern(NULL);
@@ -1274,7 +1382,8 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
->getUnder() ||
numArgs - 1 != ((GfxPatternColorSpace *)state->getStrokeColorSpace())
->getUnder()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SCN' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'SCN' command");
return;
}
for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) {
@@ -1292,7 +1401,8 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
} else {
if (numArgs != state->getStrokeColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SCN' command");
+ error(errSyntaxError, getPos(),
+ "Incorrect number of arguments in 'SCN' command");
return;
}
state->setStrokePattern(NULL);
@@ -1316,7 +1426,7 @@ void Gfx::opMoveTo(Object args[], int numArgs) {
void Gfx::opLineTo(Object args[], int numArgs) {
if (!state->isCurPt()) {
- error(getPos(), "No current point in lineto");
+ error(errSyntaxError, getPos(), "No current point in lineto");
return;
}
state->lineTo(args[0].getNum(), args[1].getNum());
@@ -1326,7 +1436,7 @@ void Gfx::opCurveTo(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto");
+ error(errSyntaxError, getPos(), "No current point in curveto");
return;
}
x1 = args[0].getNum();
@@ -1342,7 +1452,7 @@ void Gfx::opCurveTo1(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto1");
+ error(errSyntaxError, getPos(), "No current point in curveto1");
return;
}
x1 = state->getCurX();
@@ -1358,7 +1468,7 @@ void Gfx::opCurveTo2(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto2");
+ error(errSyntaxError, getPos(), "No current point in curveto2");
return;
}
x1 = args[0].getNum();
@@ -1386,7 +1496,7 @@ void Gfx::opRectangle(Object args[], int numArgs) {
void Gfx::opClosePath(Object args[], int numArgs) {
if (!state->isCurPt()) {
- error(getPos(), "No current point in closepath");
+ error(errSyntaxError, getPos(), "No current point in closepath");
return;
}
state->closePath();
@@ -1402,14 +1512,16 @@ void Gfx::opEndPath(Object args[], int numArgs) {
void Gfx::opStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in stroke");
+ //error(errSyntaxError, getPos(), "No path in stroke");
return;
}
if (state->isPath()) {
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1417,15 +1529,17 @@ void Gfx::opStroke(Object args[], int numArgs) {
void Gfx::opCloseStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/stroke");
+ //error(errSyntaxError, getPos(), "No path in closepath/stroke");
return;
}
if (state->isPath()) {
state->closePath();
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1433,14 +1547,16 @@ void Gfx::opCloseStroke(Object args[], int numArgs) {
void Gfx::opFill(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in fill");
+ //error(errSyntaxError, getPos(), "No path in fill");
return;
}
if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
}
}
doEndPath();
@@ -1448,14 +1564,16 @@ void Gfx::opFill(Object args[], int numArgs) {
void Gfx::opEOFill(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill");
+ //error(errSyntaxError, getPos(), "No path in eofill");
return;
}
if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
}
}
doEndPath();
@@ -1463,19 +1581,21 @@ void Gfx::opEOFill(Object args[], int numArgs) {
void Gfx::opFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in fill/stroke");
+ //error(errSyntaxError, getPos(), "No path in fill/stroke");
return;
}
if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1483,20 +1603,22 @@ void Gfx::opFillStroke(Object args[], int numArgs) {
void Gfx::opCloseFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/fill/stroke");
+ //error(errSyntaxError, getPos(), "No path in closepath/fill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1504,19 +1626,21 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) {
void Gfx::opEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill/stroke");
+ //error(errSyntaxError, getPos(), "No path in eofill/stroke");
return;
}
if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1524,20 +1648,22 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) {
void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/eofill/stroke");
+ //error(errSyntaxError, getPos(), "No path in closepath/eofill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1558,13 +1684,13 @@ void Gfx::doPatternFill(GBool eoFill) {
}
switch (pattern->getType()) {
case 1:
- doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill);
+ doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill, gFalse);
break;
case 2:
- doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill);
+ doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill, gFalse);
break;
default:
- error(getPos(), "Unimplemented pattern type (%d) in fill",
+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in fill",
pattern->getType());
break;
}
@@ -1585,23 +1711,68 @@ void Gfx::doPatternStroke() {
}
switch (pattern->getType()) {
case 1:
- doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse);
+ doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse, gFalse);
+ break;
+ case 2:
+ doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse, gFalse);
+ break;
+ default:
+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in stroke",
+ pattern->getType());
+ break;
+ }
+}
+
+void Gfx::doPatternText() {
+ GfxPattern *pattern;
+
+ // this is a bit of a kludge -- patterns can be really slow, so we
+ // skip them if we're only doing text extraction, since they almost
+ // certainly don't contain any text
+ if (!out->needNonText()) {
+ return;
+ }
+
+ if (!(pattern = state->getFillPattern())) {
+ return;
+ }
+ switch (pattern->getType()) {
+ case 1:
+ doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, gFalse, gTrue);
break;
case 2:
- doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse);
+ doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, gFalse, gTrue);
break;
default:
- error(getPos(), "Unimplemented pattern type (%d) in stroke",
+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in fill",
pattern->getType());
break;
}
}
+void Gfx::doPatternImageMask(Object *ref, Stream *str, int width, int height,
+ GBool invert, GBool inlineImg) {
+ saveState();
+
+ out->setSoftMaskFromImageMask(state, ref, str,
+ width, height, invert, inlineImg);
+
+ state->clearPath();
+ state->moveTo(0, 0);
+ state->lineTo(1, 0);
+ state->lineTo(1, 1);
+ state->lineTo(0, 1);
+ state->closePath();
+ doPatternFill(gTrue);
+
+ restoreState();
+}
+
void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
- GBool stroke, GBool eoFill) {
+ GBool stroke, GBool eoFill, GBool text) {
GfxPatternColorSpace *patCS;
GfxColorSpace *cs;
- GfxPath *savedPath;
+ GfxState *savedState;
double xMin, yMin, xMax, yMax, x, y, x1, y1;
double cxMin, cyMin, cxMax, cyMax;
int xi0, yi0, xi1, yi1, xi, yi;
@@ -1652,28 +1823,27 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
// save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
+ savedState = saveStateStack();
// set underlying color space (for uncolored tiling patterns); set
// various other parameters (stroke color, line width) to match
// Adobe's behavior
+ state->setFillPattern(NULL);
+ state->setStrokePattern(NULL);
if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
state->setFillColorSpace(cs->copy());
out->updateFillColorSpace(state);
state->setStrokeColorSpace(cs->copy());
out->updateStrokeColorSpace(state);
state->setStrokeColor(state->getFillColor());
+ out->updateFillColor(state);
+ out->updateStrokeColor(state);
} else {
state->setFillColorSpace(new GfxDeviceGrayColorSpace());
out->updateFillColorSpace(state);
state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
out->updateStrokeColorSpace(state);
}
- state->setFillPattern(NULL);
- out->updateFillColor(state);
- state->setStrokePattern(NULL);
- out->updateStrokeColor(state);
if (!stroke) {
state->setLineWidth(0);
out->updateLineWidth(state);
@@ -1683,7 +1853,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
if (stroke) {
state->clipToStrokePath();
out->clipToStrokePath(state);
- } else {
+ } else if (!text) {
state->clip();
if (eoFill) {
out->eoClip(state);
@@ -1754,7 +1924,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
if (out->useTilingPatternFill()) {
m1[4] = m[4];
m1[5] = m[5];
- out->tilingPatternFill(state, tPat->getContentStream(),
+ out->tilingPatternFill(state, this, tPat->getContentStream(),
tPat->getPaintType(), tPat->getResDict(),
m1, tPat->getBBox(),
xi0, yi0, xi1, yi1, xstep, ystep);
@@ -1765,22 +1935,21 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
y = yi * ystep;
m1[4] = x * m[0] + y * m[2] + m[4];
m1[5] = x * m[1] + y * m[3] + m[5];
- doForm1(tPat->getContentStream(), tPat->getResDict(),
- m1, tPat->getBBox());
+ drawForm(tPat->getContentStream(), tPat->getResDict(),
+ m1, tPat->getBBox());
}
}
}
// restore graphics state
err:
- restoreState();
- state->setPath(savedPath);
+ restoreStateStack(savedState);
}
void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
- GBool stroke, GBool eoFill) {
+ GBool stroke, GBool eoFill, GBool text) {
GfxShading *shading;
- GfxPath *savedPath;
+ GfxState *savedState;
double *ctm, *btm, *ptm;
double m[6], ictm[6], m1[6];
double xMin, yMin, xMax, yMax;
@@ -1789,27 +1958,13 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
shading = sPat->getShading();
// save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
-
- // clip to bbox
- if (shading->getHasBBox()) {
- shading->getBBox(&xMin, &yMin, &xMax, &yMax);
- state->moveTo(xMin, yMin);
- state->lineTo(xMax, yMin);
- state->lineTo(xMax, yMax);
- state->lineTo(xMin, yMax);
- state->closePath();
- state->clip();
- out->clip(state);
- state->setPath(savedPath->copy());
- }
+ savedState = saveStateStack();
// clip to current path
if (stroke) {
state->clipToStrokePath();
out->clipToStrokePath(state);
- } else {
+ } else if (!text) {
state->clip();
if (eoFill) {
out->eoClip(state);
@@ -1817,17 +1972,6 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
out->clip(state);
}
}
-
- // set the color space
- state->setFillColorSpace(shading->getColorSpace()->copy());
- out->updateFillColorSpace(state);
-
- // background color fill
- if (shading->getHasBackground()) {
- state->setFillColor(shading->getBackground());
- out->updateFillColor(state);
- out->fill(state);
- }
state->clearPath();
// construct a (pattern space) -> (current space) transform matrix
@@ -1861,11 +2005,39 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
-#if 1 //~tmp: turn off anti-aliasing temporarily
- GBool vaa = out->getVectorAntialias();
- if (vaa) {
- out->setVectorAntialias(gFalse);
+ // clip to bbox
+ if (shading->getHasBBox()) {
+ shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+
+ // set the color space
+ state->setFillColorSpace(shading->getColorSpace()->copy());
+ out->updateFillColorSpace(state);
+
+ // background color fill
+ if (shading->getHasBackground()) {
+ state->setFillColor(shading->getBackground());
+ out->updateFillColor(state);
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ out->fill(state);
+ state->clearPath();
}
+
+#if 1 //~tmp: turn off anti-aliasing temporarily
+ out->setInShading(gTrue);
#endif
// do shading type-specific operations
@@ -1890,28 +2062,28 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
}
#if 1 //~tmp: turn off anti-aliasing temporarily
- if (vaa) {
- out->setVectorAntialias(gTrue);
- }
+ out->setInShading(gFalse);
#endif
// restore graphics state
- restoreState();
- state->setPath(savedPath);
+ restoreStateStack(savedState);
}
void Gfx::opShFill(Object args[], int numArgs) {
GfxShading *shading;
- GfxPath *savedPath;
+ GfxState *savedState;
double xMin, yMin, xMax, yMax;
+ if (!ocState) {
+ return;
+ }
+
if (!(shading = res->lookupShading(args[0].getName()))) {
return;
}
// save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
+ savedState = saveStateStack();
// clip to bbox
if (shading->getHasBBox()) {
@@ -1931,10 +2103,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
out->updateFillColorSpace(state);
#if 1 //~tmp: turn off anti-aliasing temporarily
- GBool vaa = out->getVectorAntialias();
- if (vaa) {
- out->setVectorAntialias(gFalse);
- }
+ out->setInShading(gTrue);
#endif
// do shading type-specific operations
@@ -1959,14 +2128,11 @@ void Gfx::opShFill(Object args[], int numArgs) {
}
#if 1 //~tmp: turn off anti-aliasing temporarily
- if (vaa) {
- out->setVectorAntialias(gTrue);
- }
+ out->setInShading(gFalse);
#endif
// restore graphics state
- restoreState();
- state->setPath(savedPath);
+ restoreStateStack(savedState);
delete shading;
}
@@ -2100,16 +2266,16 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
double xMin, yMin, xMax, yMax;
double x0, y0, x1, y1;
double dx, dy, mul;
- GBool dxZero, dyZero;
+ GBool dxdyZero, horiz;
double tMin, tMax, t, tx, ty;
- double s[4], sMin, sMax, tmp;
+ double sMin, sMax, tmp;
double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
double t0, t1, tt;
double ta[axialMaxSplits + 1];
int next[axialMaxSplits + 1];
GfxColor color0, color1;
int nComps;
- int i, j, k, kk;
+ int i, j, k;
if (out->useShadedFills() &&
out->axialShadedFill(state, shading)) {
@@ -2124,9 +2290,9 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
shading->getCoords(&x0, &y0, &x1, &y1);
dx = x1 - x0;
dy = y1 - y0;
- dxZero = fabs(dx) < 0.01;
- dyZero = fabs(dy) < 0.01;
- if (dxZero && dyZero) {
+ dxdyZero = fabs(dx) < 0.01 && fabs(dy) < 0.01;
+ horiz = fabs(dy) < fabs(dx);
+ if (dxdyZero) {
tMin = tMax = 0;
} else {
mul = 1 / (dx * dx + dy * dy);
@@ -2170,18 +2336,16 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
// y(s) = ty + s * dx --> s = (y - ty) / dx
//
// Then look at the intersection of this line with the bounding box
- // (xMin, yMin, xMax, yMax). In the general case, there are four
- // intersection points:
+ // (xMin, yMin, xMax, yMax). For -1 < |dy/dx| < 1, look at the
+ // intersection with yMin, yMax:
//
- // s0 = (xMin - tx) / -dy
- // s1 = (xMax - tx) / -dy
- // s2 = (yMin - ty) / dx
- // s3 = (yMax - ty) / dx
+ // s0 = (yMin - ty) / dx
+ // s1 = (yMax - ty) / dx
//
- // and we want the middle two s values.
+ // else look at the intersection with xMin, xMax:
//
- // In the case where dx = 0, take s0 and s1; in the case where dy =
- // 0, take s2 and s3.
+ // s0 = (xMin - tx) / -dy
+ // s1 = (xMax - tx) / -dy
//
// Each filled polygon is bounded by two of these line segments
// perpdendicular to the t axis.
@@ -2190,13 +2354,10 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
// difference across a region is small enough, and then the region
// is painted with a single color.
- // set up: require at least one split to avoid problems when the two
- // ends of the t axis have the same color
+ // set up
nComps = shading->getColorSpace()->getNComps();
ta[0] = tMin;
- next[0] = axialMaxSplits / 2;
- ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax);
- next[axialMaxSplits / 2] = axialMaxSplits;
+ next[0] = axialMaxSplits;
ta[axialMaxSplits] = tMax;
// compute the color at t = tMin
@@ -2214,32 +2375,19 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
// bounding box
tx = x0 + tMin * dx;
ty = y0 + tMin * dy;
- if (dxZero && dyZero) {
+ if (dxdyZero) {
sMin = sMax = 0;
- } else if (dxZero) {
- sMin = (xMin - tx) / -dy;
- sMax = (xMax - tx) / -dy;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else if (dyZero) {
- sMin = (yMin - ty) / dx;
- sMax = (yMax - ty) / dx;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
} else {
- s[0] = (yMin - ty) / dx;
- s[1] = (yMax - ty) / dx;
- s[2] = (xMin - tx) / -dy;
- s[3] = (xMax - tx) / -dy;
- for (j = 0; j < 3; ++j) {
- kk = j;
- for (k = j + 1; k < 4; ++k) {
- if (s[k] < s[kk]) {
- kk = k;
- }
- }
- tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+ if (horiz) {
+ sMin = (yMin - ty) / dx;
+ sMax = (yMax - ty) / dx;
+ } else {
+ sMin = (xMin - tx) / -dy;
+ sMax = (xMax - tx) / -dy;
+ }
+ if (sMin > sMax) {
+ tmp = sMin; sMin = sMax; sMax = tmp;
}
- sMin = s[1];
- sMax = s[2];
}
ux0 = tx - sMin * dy;
uy0 = ty + sMin * dx;
@@ -2260,15 +2408,19 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
} else {
tt = t0 + (t1 - t0) * ta[j];
}
- shading->getColor(tt, &color1);
- for (k = 0; k < nComps; ++k) {
- if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
+ // require at least two splits (to avoid problems where the
+ // color doesn't change smoothly along the t axis)
+ if (j - i <= axialMaxSplits / 4) {
+ shading->getColor(tt, &color1);
+ for (k = 0; k < nComps; ++k) {
+ if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
+ break;
+ }
+ }
+ if (k == nComps) {
break;
}
}
- if (k == nComps) {
- break;
- }
k = (i + j) / 2;
ta[k] = 0.5 * (ta[i] + ta[j]);
next[i] = k;
@@ -2286,32 +2438,19 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
// bounding box
tx = x0 + ta[j] * dx;
ty = y0 + ta[j] * dy;
- if (dxZero && dyZero) {
+ if (dxdyZero) {
sMin = sMax = 0;
- } else if (dxZero) {
- sMin = (xMin - tx) / -dy;
- sMax = (xMax - tx) / -dy;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else if (dyZero) {
- sMin = (yMin - ty) / dx;
- sMax = (yMax - ty) / dx;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
} else {
- s[0] = (yMin - ty) / dx;
- s[1] = (yMax - ty) / dx;
- s[2] = (xMin - tx) / -dy;
- s[3] = (xMax - tx) / -dy;
- for (j = 0; j < 3; ++j) {
- kk = j;
- for (k = j + 1; k < 4; ++k) {
- if (s[k] < s[kk]) {
- kk = k;
- }
- }
- tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+ if (horiz) {
+ sMin = (yMin - ty) / dx;
+ sMax = (yMax - ty) / dx;
+ } else {
+ sMin = (xMin - tx) / -dy;
+ sMax = (xMax - tx) / -dy;
+ }
+ if (sMin > sMax) {
+ tmp = sMin; sMin = sMax; sMax = tmp;
}
- sMin = s[1];
- sMax = s[2];
}
ux1 = tx - sMin * dy;
uy1 = ty + sMin * dx;
@@ -2348,7 +2487,10 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
GfxColor colorA, colorB;
double xa, ya, xb, yb, ra, rb;
double ta, tb, sa, sb;
- double sz, xz, yz, sMin, sMax;
+ double sz, sMin, sMax, h;
+ double sLeft, sRight, sTop, sBottom, sZero, sDiag;
+ GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
+ GBool haveSMin, haveSMax;
GBool enclosed;
int ia, ib, k, n;
double *ctm;
@@ -2367,23 +2509,23 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
// Compute the point at which r(s) = 0; check for the enclosed
// circles case; and compute the angles for the tangent lines.
- if (x0 == x1 && y0 == y1) {
+ h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
+ if (h == 0) {
enclosed = gTrue;
theta = 0; // make gcc happy
sz = 0; // make gcc happy
- } else if (r0 == r1) {
+ } else if (r1 - r0 == 0) {
enclosed = gFalse;
theta = 0;
sz = 0; // make gcc happy
+ } else if (fabs(r1 - r0) >= h) {
+ enclosed = gTrue;
+ theta = 0; // make gcc happy
+ sz = 0; // make gcc happy
} else {
+ enclosed = gFalse;
sz = -r0 / (r1 - r0);
- xz = x0 + sz * (x1 - x0);
- yz = y0 + sz * (y1 - y0);
- enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0;
- theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz)));
- if (r0 > r1) {
- theta = -theta;
- }
+ theta = asin((r1 - r0) / h);
}
if (enclosed) {
alpha = 0;
@@ -2397,59 +2539,101 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
sMin = 0;
sMax = 1;
} else {
- sMin = 1;
- sMax = 0;
- // solve for x(s) + r(s) = xMin
- if ((x1 + r1) - (x0 + r0) != 0) {
- sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
+ // solve x(sLeft) + r(sLeft) = xMin
+ if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
+ sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
+ } else {
+ sLeft = 0; // make gcc happy
}
- // solve for x(s) - r(s) = xMax
- if ((x1 - r1) - (x0 - r0) != 0) {
- sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
+ // solve x(sRight) - r(sRight) = xMax
+ if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
+ sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
+ } else {
+ sRight = 0; // make gcc happy
}
- // solve for y(s) + r(s) = yMin
- if ((y1 + r1) - (y0 + r0) != 0) {
- sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
+ // solve y(sBottom) + r(sBottom) = yMin
+ if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
+ sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
+ } else {
+ sBottom = 0; // make gcc happy
}
- // solve for y(s) - r(s) = yMax
- if ((y1 - r1) - (y0 - r0) != 0) {
- sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
+ // solve y(sTop) - r(sTop) = yMax
+ if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
+ sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
+ } else {
+ sTop = 0; // make gcc happy
+ }
+ // solve r(sZero) = 0
+ if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
+ sZero = -r0 / (r1 - r0);
+ } else {
+ sZero = 0; // make gcc happy
+ }
+ // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
+ if (haveSZero) {
+ sDiag = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ } else {
+ sDiag = 0; // make gcc happy
}
- // check against sz
- if (r0 < r1) {
- if (sMin < sz) {
- sMin = sz;
+ // compute sMin
+ if (shading->getExtend0()) {
+ sMin = 0;
+ haveSMin = gFalse;
+ if (x0 < x1 && haveSLeft && sLeft < 0) {
+ sMin = sLeft;
+ haveSMin = gTrue;
+ } else if (x0 > x1 && haveSRight && sRight < 0) {
+ sMin = sRight;
+ haveSMin = gTrue;
}
- } else if (r0 > r1) {
- if (sMax > sz) {
- sMax = sz;
+ if (y0 < y1 && haveSBottom && sBottom < 0) {
+ if (!haveSMin || sBottom > sMin) {
+ sMin = sBottom;
+ haveSMin = gTrue;
+ }
+ } else if (y0 > y1 && haveSTop && sTop < 0) {
+ if (!haveSMin || sTop > sMin) {
+ sMin = sTop;
+ haveSMin = gTrue;
+ }
}
- }
- // check the 'extend' flags
- if (!shading->getExtend0() && sMin < 0) {
+ if (haveSZero && sZero < 0) {
+ if (!haveSMin || sZero > sMin) {
+ sMin = sZero;
+ }
+ }
+ } else {
sMin = 0;
}
- if (!shading->getExtend1() && sMax > 1) {
+ // compute sMax
+ if (shading->getExtend1()) {
+ sMax = 1;
+ haveSMax = gFalse;
+ if (x1 < x0 && haveSLeft && sLeft > 1) {
+ sMax = sLeft;
+ haveSMax = gTrue;
+ } else if (x1 > x0 && haveSRight && sRight > 1) {
+ sMax = sRight;
+ haveSMax = gTrue;
+ }
+ if (y1 < y0 && haveSBottom && sBottom > 1) {
+ if (!haveSMax || sBottom < sMax) {
+ sMax = sBottom;
+ haveSMax = gTrue;
+ }
+ } else if (y1 > y0 && haveSTop && sTop > 1) {
+ if (!haveSMax || sTop < sMax) {
+ sMax = sTop;
+ haveSMax = gTrue;
+ }
+ }
+ if (haveSZero && sDiag > 1) {
+ if (!haveSMax || sDiag < sMax) {
+ sMax = sDiag;
+ }
+ }
+ } else {
sMax = 1;
}
}
@@ -2922,6 +3106,7 @@ void Gfx::opBeginText(Object args[], int numArgs) {
out->updateTextMat(state);
out->updateTextPos(state);
fontChanged = gTrue;
+ textClipBBoxEmpty = gTrue;
}
void Gfx::opEndText(Object args[], int numArgs) {
@@ -3028,23 +3213,27 @@ void Gfx::opTextNextLine(Object args[], int numArgs) {
void Gfx::opShowText(Object args[], int numArgs) {
if (!state->getFont()) {
- error(getPos(), "No font in show");
+ error(errSyntaxError, getPos(), "No font in show");
return;
}
if (fontChanged) {
out->updateFont(state);
fontChanged = gFalse;
}
- out->beginStringOp(state);
- doShowText(args[0].getString());
- out->endStringOp(state);
+ if (ocState) {
+ out->beginStringOp(state);
+ doShowText(args[0].getString());
+ out->endStringOp(state);
+ } else {
+ doIncCharCount(args[0].getString());
+ }
}
void Gfx::opMoveShowText(Object args[], int numArgs) {
double tx, ty;
if (!state->getFont()) {
- error(getPos(), "No font in move/show");
+ error(errSyntaxError, getPos(), "No font in move/show");
return;
}
if (fontChanged) {
@@ -3055,16 +3244,20 @@ void Gfx::opMoveShowText(Object args[], int numArgs) {
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
out->updateTextPos(state);
- out->beginStringOp(state);
- doShowText(args[0].getString());
- out->endStringOp(state);
+ if (ocState) {
+ out->beginStringOp(state);
+ doShowText(args[0].getString());
+ out->endStringOp(state);
+ } else {
+ doIncCharCount(args[0].getString());
+ }
}
void Gfx::opMoveSetShowText(Object args[], int numArgs) {
double tx, ty;
if (!state->getFont()) {
- error(getPos(), "No font in move/set/show");
+ error(errSyntaxError, getPos(), "No font in move/set/show");
return;
}
if (fontChanged) {
@@ -3079,9 +3272,13 @@ void Gfx::opMoveSetShowText(Object args[], int numArgs) {
out->updateWordSpace(state);
out->updateCharSpace(state);
out->updateTextPos(state);
- out->beginStringOp(state);
- doShowText(args[2].getString());
- out->endStringOp(state);
+ if (ocState) {
+ out->beginStringOp(state);
+ doShowText(args[2].getString());
+ out->endStringOp(state);
+ } else {
+ doIncCharCount(args[2].getString());
+ }
}
void Gfx::opShowSpaceText(Object args[], int numArgs) {
@@ -3091,37 +3288,48 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) {
int i;
if (!state->getFont()) {
- error(getPos(), "No font in show/space");
+ error(errSyntaxError, getPos(), "No font in show/space");
return;
}
if (fontChanged) {
out->updateFont(state);
fontChanged = gFalse;
}
- out->beginStringOp(state);
- wMode = state->getFont()->getWMode();
- a = args[0].getArray();
- for (i = 0; i < a->getLength(); ++i) {
- a->get(i, &obj);
- if (obj.isNum()) {
- // this uses the absolute value of the font size to match
- // Acrobat's behavior
- if (wMode) {
- state->textShift(0, -obj.getNum() * 0.001 *
- fabs(state->getFontSize()));
+ if (ocState) {
+ out->beginStringOp(state);
+ wMode = state->getFont()->getWMode();
+ a = args[0].getArray();
+ for (i = 0; i < a->getLength(); ++i) {
+ a->get(i, &obj);
+ if (obj.isNum()) {
+ if (wMode) {
+ state->textShift(0, -obj.getNum() * 0.001 *
+ state->getFontSize());
+ } else {
+ state->textShift(-obj.getNum() * 0.001 *
+ state->getFontSize() *
+ state->getHorizScaling(), 0);
+ }
+ out->updateTextShift(state, obj.getNum());
+ } else if (obj.isString()) {
+ doShowText(obj.getString());
} else {
- state->textShift(-obj.getNum() * 0.001 *
- fabs(state->getFontSize()), 0);
+ error(errSyntaxError, getPos(),
+ "Element of show/space array must be number or string");
}
- out->updateTextShift(state, obj.getNum());
- } else if (obj.isString()) {
- doShowText(obj.getString());
- } else {
- error(getPos(), "Element of show/space array must be number or string");
+ obj.free();
+ }
+ out->endStringOp(state);
+ } else {
+ a = args[0].getArray();
+ for (i = 0; i < a->getLength(); ++i) {
+ a->get(i, &obj);
+ if (obj.isString()) {
+ doIncCharCount(obj.getString());
+ }
+ obj.free();
}
- obj.free();
}
- out->endStringOp(state);
}
void Gfx::doShowText(GString *s) {
@@ -3130,14 +3338,18 @@ void Gfx::doShowText(GString *s) {
double riseX, riseY;
CharCode code;
Unicode u[8];
- double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
+ double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, ddx, ddy;
double originX, originY, tOriginX, tOriginY;
+ double x0, y0, x1, y1;
double oldCTM[6], newCTM[6];
double *mat;
Object charProc;
Dict *resDict;
Parser *oldParser;
+ GfxState *savedState;
char *p;
+ int render;
+ GBool patternFill;
int len, n, uLen, nChars, nSpaces, i;
font = state->getFont();
@@ -3147,6 +3359,28 @@ void Gfx::doShowText(GString *s) {
out->beginString(state, s);
}
+ // if we're doing a pattern fill, set up clipping
+ render = state->getRender();
+ if (!(render & 1) &&
+ state->getFillColorSpace()->getMode() == csPattern) {
+ patternFill = gTrue;
+ saveState();
+ // disable fill, enable clipping, leave stroke unchanged
+ if ((render ^ (render >> 1)) & 1) {
+ render = 5;
+ } else {
+ render = 7;
+ }
+ state->setRender(render);
+ out->updateRender(state);
+ } else {
+ patternFill = gFalse;
+ }
+
+ state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
+ x0 = state->getCurX() + riseX;
+ y0 = state->getCurY() + riseY;
+
// handle a Type 3 char
if (font->getType() == fontType3 && out->interpretType3Chars()) {
mat = state->getCTM();
@@ -3169,11 +3403,8 @@ void Gfx::doShowText(GString *s) {
newCTM[3] *= state->getFontSize();
newCTM[0] *= state->getHorizScaling();
newCTM[2] *= state->getHorizScaling();
- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
curX = state->getCurX();
curY = state->getCurY();
- lineX = state->getLineX();
- lineY = state->getLineY();
oldParser = parser;
p = s->getCString();
len = s->getLength();
@@ -3189,11 +3420,12 @@ void Gfx::doShowText(GString *s) {
dy *= state->getFontSize();
state->textTransformDelta(dx, dy, &tdx, &tdy);
state->transform(curX + riseX, curY + riseY, &x, &y);
- saveState();
+ savedState = saveStateStack();
state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
//~ the CTM concat values here are wrong (but never used)
out->updateCTM(state, 1, 0, 0, 1, 0, 0);
- if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy,
+ state->transformDelta(dx, dy, &ddx, &ddy);
+ if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy,
code, u, uLen)) {
((Gfx8BitFont *)font)->getCharProc(code, &charProc);
if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
@@ -3202,7 +3434,8 @@ void Gfx::doShowText(GString *s) {
if (charProc.isStream()) {
display(&charProc, gFalse);
} else {
- error(getPos(), "Missing or bad Type3 CharProc entry");
+ error(errSyntaxError, getPos(),
+ "Missing or bad Type3 CharProc entry");
}
out->endType3Char(state);
if (resDict) {
@@ -3210,20 +3443,16 @@ void Gfx::doShowText(GString *s) {
}
charProc.free();
}
- restoreState();
- // GfxState::restore() does *not* restore the current position,
- // so we deal with it here using (curX, curY) and (lineX, lineY)
+ restoreStateStack(savedState);
curX += tdx;
curY += tdy;
state->moveTo(curX, curY);
- state->textSetPos(lineX, lineY);
p += n;
len -= n;
}
parser = oldParser;
} else if (out->useDrawChar()) {
- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
p = s->getCString();
len = s->getLength();
while (len > 0) {
@@ -3294,9 +3523,52 @@ void Gfx::doShowText(GString *s) {
out->endString(state);
}
+ if (patternFill) {
+ out->saveTextPos(state);
+ // tell the OutputDev to do the clipping
+ out->endTextObject(state);
+ // set up a clipping bbox so doPatternText will work -- assume
+ // that the text bounding box does not extend past the baseline in
+ // any direction by more than twice the font size
+ x1 = state->getCurX() + riseX;
+ y1 = state->getCurY() + riseY;
+ if (x0 > x1) {
+ x = x0; x0 = x1; x1 = x;
+ }
+ if (y0 > y1) {
+ y = y0; y0 = y1; y1 = y;
+ }
+ state->textTransformDelta(0, state->getFontSize(), &dx, &dy);
+ state->textTransformDelta(state->getFontSize(), 0, &dx2, &dy2);
+ dx = fabs(dx);
+ dx2 = fabs(dx2);
+ if (dx2 > dx) {
+ dx = dx2;
+ }
+ dy = fabs(dy);
+ dy2 = fabs(dy2);
+ if (dy2 > dy) {
+ dy = dy2;
+ }
+ state->clipToRect(x0 - 2 * dx, y0 - 2 * dy, x1 + 2 * dx, y1 + 2 * dy);
+ // set render mode to fill-only
+ state->setRender(0);
+ out->updateRender(state);
+ doPatternText();
+ restoreState();
+ out->restoreTextPos(state);
+ }
+
updateLevel += 10 * s->getLength();
}
+// NB: this is only called when ocState is false.
+void Gfx::doIncCharCount(GString *s) {
+ if (out->needCharCount()) {
+ out->incCharCount(s->getLength());
+ }
+}
+
//------------------------------------------------------------------------
// XObject operators
//------------------------------------------------------------------------
@@ -3308,12 +3580,15 @@ void Gfx::opXObject(Object args[], int numArgs) {
Object opiDict;
#endif
+ if (!ocState && !out->needCharCount()) {
+ return;
+ }
name = args[0].getName();
if (!res->lookupXObject(name, &obj1)) {
return;
}
if (!obj1.isStream()) {
- error(getPos(), "XObject '%s' is wrong type", name);
+ error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name);
obj1.free();
return;
}
@@ -3343,9 +3618,11 @@ void Gfx::opXObject(Object args[], int numArgs) {
out->psXObject(obj1.getStream(),
obj3.isStream() ? obj3.getStream() : (Stream *)NULL);
} else if (obj2.isName()) {
- error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
+ error(errSyntaxError, getPos(),
+ "Unknown XObject subtype '{0:s}'", obj2.getName());
} else {
- error(getPos(), "XObject subtype is missing or wrong type");
+ error(errSyntaxError, getPos(),
+ "XObject subtype is missing or wrong type");
}
obj2.free();
#if OPI_SUPPORT
@@ -3373,7 +3650,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
GBool maskInvert;
Stream *maskStr;
Object obj1, obj2;
- int i;
+ int i, n;
// get info from the stream
bits = 0;
@@ -3389,19 +3666,27 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
obj1.free();
dict->lookup("W", &obj1);
}
- if (!obj1.isInt())
+ if (!obj1.isInt()) {
goto err2;
+ }
width = obj1.getInt();
obj1.free();
+ if (width <= 0) {
+ goto err1;
+ }
dict->lookup("Height", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("H", &obj1);
}
- if (!obj1.isInt())
+ if (!obj1.isInt()) {
goto err2;
+ }
height = obj1.getInt();
obj1.free();
+ if (height <= 0) {
+ goto err1;
+ }
// image or mask?
dict->lookup("ImageMask", &obj1);
@@ -3447,16 +3732,30 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
- if (obj2.isInt() && obj2.getInt() == 1)
- invert = gTrue;
+ invert = obj2.isNum() && obj2.getNum() == 1;
obj2.free();
} else if (!obj1.isNull()) {
goto err2;
}
obj1.free();
+ // if drawing is disabled, skip over inline image data
+ if (!ocState) {
+ str->reset();
+ n = height * ((width + 7) / 8);
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+ str->close();
+
// draw it
- out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+ } else {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternImageMask(ref, str, width, height, invert, inlineImg);
+ } else {
+ out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+ }
+ }
} else {
@@ -3581,14 +3880,36 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
haveSoftMask = gTrue;
} else if (maskObj.isArray()) {
// color key mask
+ haveColorKeyMask = gTrue;
for (i = 0;
- i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps;
- ++i) {
+ i+1 < maskObj.arrayGetLength() && i+1 < 2*gfxColorMaxComps;
+ i += 2) {
maskObj.arrayGet(i, &obj1);
+ if (!obj1.isInt()) {
+ obj1.free();
+ haveColorKeyMask = gFalse;
+ break;
+ }
maskColors[i] = obj1.getInt();
obj1.free();
+ if (maskColors[i] < 0 || maskColors[i] >= (1 << bits)) {
+ haveColorKeyMask = gFalse;
+ break;
+ }
+ maskObj.arrayGet(i+1, &obj1);
+ if (!obj1.isInt()) {
+ obj1.free();
+ haveColorKeyMask = gFalse;
+ break;
+ }
+ maskColors[i+1] = obj1.getInt();
+ obj1.free();
+ if (maskColors[i+1] < 0 || maskColors[i+1] >= (1 << bits) ||
+ maskColors[i] > maskColors[i+1]) {
+ haveColorKeyMask = gFalse;
+ break;
+ }
}
- haveColorKeyMask = gTrue;
} else if (maskObj.isStream()) {
// explicit mask
if (inlineImg) {
@@ -3633,9 +3954,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
- if (obj2.isInt() && obj2.getInt() == 1) {
- maskInvert = gTrue;
- }
+ maskInvert = obj2.isNum() && obj2.getNum() == 1;
obj2.free();
} else if (!obj1.isNull()) {
goto err2;
@@ -3644,20 +3963,32 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
haveExplicitMask = gTrue;
}
+ // if drawing is disabled, skip over inline image data
+ if (!ocState) {
+ str->reset();
+ n = height * ((width * colorMap->getNumPixelComps() *
+ colorMap->getBits() + 7) / 8);
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+ str->close();
+
// draw it
- if (haveSoftMask) {
- out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskColorMap);
- delete maskColorMap;
- } else if (haveExplicitMask) {
- out->drawMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskInvert);
} else {
- out->drawImage(state, ref, str, width, height, colorMap,
- haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
+ if (haveSoftMask) {
+ out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
+ maskStr, maskWidth, maskHeight, maskColorMap);
+ delete maskColorMap;
+ } else if (haveExplicitMask) {
+ out->drawMaskedImage(state, ref, str, width, height, colorMap,
+ maskStr, maskWidth, maskHeight, maskInvert);
+ } else {
+ out->drawImage(state, ref, str, width, height, colorMap,
+ haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
+ }
}
- delete colorMap;
+ delete colorMap;
maskObj.free();
smaskObj.free();
}
@@ -3672,7 +4003,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
err2:
obj1.free();
err1:
- error(getPos(), "Bad image parameters");
+ error(errSyntaxError, getPos(), "Bad image parameters");
}
void Gfx::doForm(Object *str) {
@@ -3683,11 +4014,12 @@ void Gfx::doForm(Object *str) {
double m[6], bbox[4];
Object resObj;
Dict *resDict;
+ GBool oc, ocSaved;
Object obj1, obj2, obj3;
int i;
// check for excessive recursion
- if (formDepth > 20) {
+ if (formDepth > 100) {
return;
}
@@ -3697,7 +4029,20 @@ void Gfx::doForm(Object *str) {
// check form type
dict->lookup("FormType", &obj1);
if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(getPos(), "Unknown form type");
+ error(errSyntaxError, getPos(), "Unknown form type");
+ }
+ obj1.free();
+
+ // check for optional content key
+ ocSaved = ocState;
+ dict->lookupNF("OC", &obj1);
+ if (doc->getOptionalContent()->evalOCObject(&obj1, &oc) && !oc) {
+ obj1.free();
+ if (out->needCharCount()) {
+ ocState = gFalse;
+ } else {
+ return;
+ }
}
obj1.free();
@@ -3705,7 +4050,8 @@ void Gfx::doForm(Object *str) {
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
bboxObj.free();
- error(getPos(), "Bad form bounding box");
+ error(errSyntaxError, getPos(), "Bad form bounding box");
+ ocState = ocSaved;
return;
}
for (i = 0; i < 4; ++i) {
@@ -3759,23 +4105,26 @@ void Gfx::doForm(Object *str) {
// draw it
++formDepth;
- doForm1(str, resDict, m, bbox,
- transpGroup, gFalse, blendingColorSpace, isolated, knockout);
+ drawForm(str, resDict, m, bbox,
+ transpGroup, gFalse, blendingColorSpace, isolated, knockout);
--formDepth;
if (blendingColorSpace) {
delete blendingColorSpace;
}
resObj.free();
+
+ ocState = ocSaved;
}
-void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
- GBool transpGroup, GBool softMask,
- GfxColorSpace *blendingColorSpace,
- GBool isolated, GBool knockout,
- GBool alpha, Function *transferFunc,
- GfxColor *backdropColor) {
+void Gfx::drawForm(Object *str, Dict *resDict, double *matrix, double *bbox,
+ GBool transpGroup, GBool softMask,
+ GfxColorSpace *blendingColorSpace,
+ GBool isolated, GBool knockout,
+ GBool alpha, Function *transferFunc,
+ GfxColor *backdropColor) {
Parser *oldParser;
+ GfxState *savedState;
double oldBaseMatrix[6];
int i;
@@ -3783,7 +4132,7 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
pushResources(resDict);
// save current graphics state
- saveState();
+ savedState = saveStateStack();
// kill any pre-existing path
state->clearPath();
@@ -3847,7 +4196,7 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
parser = oldParser;
// restore graphics state
- restoreState();
+ restoreStateStack(savedState);
// pop resource stack
popResources();
@@ -3869,6 +4218,9 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
Stream *str;
int c1, c2;
+ // NB: this function is run even if ocState is false -- doImage() is
+ // responsible for skipping over the inline image data
+
// build dict/stream
str = buildImageStream();
@@ -3898,7 +4250,8 @@ Stream *Gfx::buildImageStream() {
parser->getObj(&obj);
while (!obj.isCmd("ID") && !obj.isEOF()) {
if (!obj.isName()) {
- error(getPos(), "Inline image dictionary key must be a name object");
+ error(errSyntaxError, getPos(),
+ "Inline image dictionary key must be a name object");
obj.free();
} else {
key = copyString(obj.getName());
@@ -3913,7 +4266,7 @@ Stream *Gfx::buildImageStream() {
parser->getObj(&obj);
}
if (obj.isEOF()) {
- error(getPos(), "End of file in inline image");
+ error(errSyntaxError, getPos(), "End of file in inline image");
obj.free();
dict.free();
return NULL;
@@ -3921,18 +4274,23 @@ Stream *Gfx::buildImageStream() {
obj.free();
// make stream
- str = new EmbedStream(parser->getStream(), &dict, gFalse, 0);
+ if (!(str = parser->getStream())) {
+ error(errSyntaxError, getPos(), "Invalid inline image data");
+ dict.free();
+ return NULL;
+ }
+ str = new EmbedStream(str, &dict, gFalse, 0);
str = str->addFilters(&dict);
return str;
}
void Gfx::opImageData(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'ID' operator");
+ error(errInternal, getPos(), "Got 'ID' operator");
}
void Gfx::opEndImage(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'EI' operator");
+ error(errInternal, getPos(), "Got 'EI' operator");
}
//------------------------------------------------------------------------
@@ -3967,23 +4325,88 @@ void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
//------------------------------------------------------------------------
void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
+ GfxMarkedContent *mc;
+ Object obj;
+ GBool ocStateNew;
+ GString *s;
+ Unicode *u;
+ int uLen, i;
+ GfxMarkedContentKind mcKind;
+
if (printCommands) {
printf(" marked content: %s ", args[0].getName());
- if (numArgs == 2)
- args[2].print(stdout);
+ if (numArgs == 2) {
+ args[1].print(stdout);
+ }
printf("\n");
fflush(stdout);
}
+ mcKind = gfxMCOther;
+ if (args[0].isName("OC") && numArgs == 2 && args[1].isName() &&
+ res->lookupPropertiesNF(args[1].getName(), &obj)) {
+ if (doc->getOptionalContent()->evalOCObject(&obj, &ocStateNew)) {
+ ocState = ocStateNew;
+ }
+ obj.free();
+ mcKind = gfxMCOptionalContent;
+ } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) {
+ if (args[1].dictLookup("ActualText", &obj)->isString()) {
+ s = obj.getString();
+ if ((s->getChar(0) & 0xff) == 0xfe &&
+ (s->getChar(1) & 0xff) == 0xff) {
+ uLen = (s->getLength() - 2) / 2;
+ u = (Unicode *)gmallocn(uLen, sizeof(Unicode));
+ for (i = 0; i < uLen; ++i) {
+ u[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
+ (s->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ uLen = s->getLength();
+ u = (Unicode *)gmallocn(uLen, sizeof(Unicode));
+ for (i = 0; i < uLen; ++i) {
+ u[i] = pdfDocEncoding[s->getChar(i) & 0xff];
+ }
+ }
+ out->beginActualText(state, u, uLen);
+ gfree(u);
+ mcKind = gfxMCActualText;
+ }
+ obj.free();
+ }
+ mc = new GfxMarkedContent(mcKind, ocState);
+ markedContentStack->append(mc);
}
void Gfx::opEndMarkedContent(Object args[], int numArgs) {
+ GfxMarkedContent *mc;
+ GfxMarkedContentKind mcKind;
+
+ if (markedContentStack->getLength() > 0) {
+ mc = (GfxMarkedContent *)
+ markedContentStack->del(markedContentStack->getLength() - 1);
+ mcKind = mc->kind;
+ delete mc;
+ if (mcKind == gfxMCOptionalContent) {
+ if (markedContentStack->getLength() > 0) {
+ mc = (GfxMarkedContent *)
+ markedContentStack->get(markedContentStack->getLength() - 1);
+ ocState = mc->ocState;
+ } else {
+ ocState = gTrue;
+ }
+ } else if (mcKind == gfxMCActualText) {
+ out->endActualText(state);
+ }
+ } else {
+ error(errSyntaxWarning, getPos(), "Mismatched EMC operator");
+ }
}
void Gfx::opMarkPoint(Object args[], int numArgs) {
if (printCommands) {
printf(" mark point: %s ", args[0].getName());
if (numArgs == 2)
- args[2].print(stdout);
+ args[1].print(stdout);
printf("\n");
fflush(stdout);
}
@@ -3996,45 +4419,23 @@ void Gfx::opMarkPoint(Object args[], int numArgs) {
void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
double xMin, double yMin, double xMax, double yMax) {
Dict *dict, *resDict;
- Object matrixObj, bboxObj, resObj;
- Object obj1;
- double m[6], bbox[4], ictm[6];
- double *ctm;
- double formX0, formY0, formX1, formY1;
- double annotX0, annotY0, annotX1, annotY1;
- double det, x, y, sx, sy;
+ Object matrixObj, bboxObj, resObj, obj1;
+ double formXMin, formYMin, formXMax, formYMax;
+ double x, y, sx, sy, tx, ty;
+ double m[6], bbox[4];
double r, g, b;
GfxColor color;
double *dash, *dash2;
int dashLength;
int i;
- //~ can we assume that we're in default user space?
- //~ (i.e., baseMatrix = ctm)
+ // this function assumes that we are in the default user space,
+ // i.e., baseMatrix = ctm
- // transform the annotation bbox from default user space to user
- // space: (bbox * baseMatrix) * iCTM
- ctm = state->getCTM();
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
- x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4];
- y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5];
- annotX0 = ictm[0] * x + ictm[2] * y + ictm[4];
- annotY0 = ictm[1] * x + ictm[3] * y + ictm[5];
- x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4];
- y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5];
- annotX1 = ictm[0] * x + ictm[2] * y + ictm[4];
- annotY1 = ictm[1] * x + ictm[3] * y + ictm[5];
- if (annotX0 > annotX1) {
- x = annotX0; annotX0 = annotX1; annotX1 = x;
- }
- if (annotY0 > annotY1) {
- y = annotY0; annotY0 = annotY1; annotY1 = y;
+ // if the bounding box has zero width or height, don't draw anything
+ // at all
+ if (xMin == xMax || yMin == yMax) {
+ return;
}
// draw the appearance stream (if there is one)
@@ -4047,7 +4448,7 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
bboxObj.free();
- error(getPos(), "Bad form bounding box");
+ error(errSyntaxError, getPos(), "Bad form bounding box");
return;
}
for (i = 0; i < 4; ++i) {
@@ -4072,44 +4473,82 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
}
matrixObj.free();
- // transform the form bbox from form space to user space
- formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
- formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
- formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
- formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
- if (formX0 > formX1) {
- x = formX0; formX0 = formX1; formX1 = x;
+ // transform the four corners of the form bbox to default user
+ // space, and construct the transformed bbox
+ x = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
+ y = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
+ formXMin = formXMax = x;
+ formYMin = formYMax = y;
+ x = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
+ y = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
+ if (x < formXMin) {
+ formXMin = x;
+ } else if (x > formXMax) {
+ formXMax = x;
+ }
+ if (y < formYMin) {
+ formYMin = y;
+ } else if (y > formYMax) {
+ formYMax = y;
+ }
+ x = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
+ y = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
+ if (x < formXMin) {
+ formXMin = x;
+ } else if (x > formXMax) {
+ formXMax = x;
+ }
+ if (y < formYMin) {
+ formYMin = y;
+ } else if (y > formYMax) {
+ formYMax = y;
+ }
+ x = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
+ y = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
+ if (x < formXMin) {
+ formXMin = x;
+ } else if (x > formXMax) {
+ formXMax = x;
}
- if (formY0 > formY1) {
- y = formY0; formY0 = formY1; formY1 = y;
+ if (y < formYMin) {
+ formYMin = y;
+ } else if (y > formYMax) {
+ formYMax = y;
}
- // scale the form to fit the annotation bbox
- if (formX1 == formX0) {
+ // construct a mapping matrix, [sx 0 0], which maps the transformed
+ // [0 sy 0]
+ // [tx ty 1]
+ // bbox to the annotation rectangle
+ if (formXMin == formXMax) {
// this shouldn't happen
sx = 1;
} else {
- sx = (annotX1 - annotX0) / (formX1 - formX0);
+ sx = (xMax - xMin) / (formXMax - formXMin);
}
- if (formY1 == formY0) {
+ if (formYMin == formYMax) {
// this shouldn't happen
sy = 1;
} else {
- sy = (annotY1 - annotY0) / (formY1 - formY0);
+ sy = (yMax - yMin) / (formYMax - formYMin);
}
+ tx = -formXMin * sx + xMin;
+ ty = -formYMin * sy + yMin;
+
+ // the final transform matrix is (form matrix) * (mapping matrix)
m[0] *= sx;
- m[2] *= sx;
- m[4] = (m[4] - formX0) * sx + annotX0;
m[1] *= sy;
+ m[2] *= sx;
m[3] *= sy;
- m[5] = (m[5] - formY0) * sy + annotY0;
+ m[4] = m[4] * sx + tx;
+ m[5] = m[5] * sy + ty;
- // get resources
+ // get the resources
dict->lookup("Resources", &resObj);
resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
// draw it
- doForm1(str, resDict, m, bbox);
+ drawForm(str, resDict, m, bbox);
resObj.free();
}
@@ -4127,31 +4566,22 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
color.c[2] = dblToCol(b);
state->setStrokeColor(&color);
out->updateStrokeColor(state);
- // compute the width scale factor when going from default user
- // space to user space
- x = (baseMatrix[0] + baseMatrix[2]) * ictm[0] +
- (baseMatrix[1] + baseMatrix[3]) * ictm[2];
- y = (baseMatrix[0] + baseMatrix[2]) * ictm[1] +
- (baseMatrix[1] + baseMatrix[3]) * ictm[3];
- x = sqrt(0.5 * (x * x + y * y));
- state->setLineWidth(x * borderStyle->getWidth());
+ state->setLineWidth(borderStyle->getWidth());
out->updateLineWidth(state);
borderStyle->getDash(&dash, &dashLength);
if (borderStyle->getType() == annotBorderDashed && dashLength > 0) {
dash2 = (double *)gmallocn(dashLength, sizeof(double));
- for (i = 0; i < dashLength; ++i) {
- dash2[i] = x * dash[i];
- }
+ memcpy(dash2, dash, dashLength * sizeof(double));
state->setLineDash(dash2, dashLength, 0);
out->updateLineDash(state);
}
//~ this doesn't currently handle the beveled and engraved styles
state->clearPath();
- state->moveTo(annotX0, out->upsideDown() ? annotY1 : annotY0);
- state->lineTo(annotX1, out->upsideDown() ? annotY1 : annotY0);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
if (borderStyle->getType() != annotBorderUnderlined) {
- state->lineTo(annotX1, out->upsideDown() ? annotY0 : annotY1);
- state->lineTo(annotX0, out->upsideDown() ? annotY0 : annotY1);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
state->closePath();
}
out->stroke(state);
@@ -4168,6 +4598,27 @@ void Gfx::restoreState() {
out->restoreState(state);
}
+// Create a new state stack, and initialize it with a copy of the
+// current state.
+GfxState *Gfx::saveStateStack() {
+ GfxState *oldState;
+
+ out->saveState(state);
+ oldState = state;
+ state = state->copy(gTrue);
+ return oldState;
+}
+
+// Switch back to the previous state stack.
+void Gfx::restoreStateStack(GfxState *oldState) {
+ while (state->hasSaves()) {
+ restoreState();
+ }
+ delete state;
+ state = oldState;
+ out->restoreState(state);
+}
+
void Gfx::pushResources(Dict *resDict) {
res = new GfxResources(xref, resDict, res);
}
diff --git a/xpdf/Gfx.h b/xpdf/Gfx.h
index 0e4263c..2753766 100644
--- a/xpdf/Gfx.h
+++ b/xpdf/Gfx.h
@@ -18,6 +18,8 @@
#include "gtypes.h"
class GString;
+class GList;
+class PDFDoc;
class XRef;
class Array;
class Stream;
@@ -88,6 +90,7 @@ public:
GfxPattern *lookupPattern(char *name);
GfxShading *lookupShading(char *name);
GBool lookupGState(char *name, Object *obj);
+ GBool lookupPropertiesNF(char *name, Object *obj);
GfxResources *getNext() { return next; }
@@ -99,10 +102,35 @@ private:
Object patternDict;
Object shadingDict;
Object gStateDict;
+ Object propsDict;
GfxResources *next;
};
//------------------------------------------------------------------------
+// GfxMarkedContent
+//------------------------------------------------------------------------
+
+enum GfxMarkedContentKind {
+ gfxMCOptionalContent,
+ gfxMCActualText,
+ gfxMCOther
+};
+
+class GfxMarkedContent {
+public:
+
+ GfxMarkedContent(GfxMarkedContentKind kindA, GBool ocStateA) {
+ kind = kindA;
+ ocState = ocStateA;
+ }
+ ~GfxMarkedContent() {}
+
+ GfxMarkedContentKind kind;
+ GBool ocState; // true if drawing is enabled, false if
+ // disabled
+};
+
+//------------------------------------------------------------------------
// Gfx
//------------------------------------------------------------------------
@@ -110,14 +138,14 @@ class Gfx {
public:
// Constructor for regular output.
- Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+ Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict,
double hDPI, double vDPI, PDFRectangle *box,
PDFRectangle *cropBox, int rotate,
GBool (*abortCheckCbkA)(void *data) = NULL,
void *abortCheckCbkDataA = NULL);
// Constructor for a sub-page object.
- Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+ Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
PDFRectangle *box, PDFRectangle *cropBox,
GBool (*abortCheckCbkA)(void *data) = NULL,
void *abortCheckCbkDataA = NULL);
@@ -141,8 +169,16 @@ public:
// Get the current graphics state object.
GfxState *getState() { return state; }
+ void drawForm(Object *str, Dict *resDict, double *matrix, double *bbox,
+ GBool transpGroup = gFalse, GBool softMask = gFalse,
+ GfxColorSpace *blendingColorSpace = NULL,
+ GBool isolated = gFalse, GBool knockout = gFalse,
+ GBool alpha = gFalse, Function *transferFunc = NULL,
+ GfxColor *backdropColor = NULL);
+
private:
+ PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
OutputDev *out; // output device
GBool subPage; // is this a sub-page object?
@@ -157,6 +193,12 @@ private:
double baseMatrix[6]; // default matrix for most recent
// page/form/pattern
int formDepth;
+ double textClipBBox[4]; // text clipping bounding box
+ GBool textClipBBoxEmpty; // true if textClipBBox has not been
+ // initialized yet
+ GBool ocState; // true if drawing is enabled, false if
+ // disabled
+ GList *markedContentStack; // BMC/BDC/EMC stack [GfxMarkedContent]
Parser *parser; // parser for page content stream(s)
@@ -224,10 +266,13 @@ private:
void opCloseEOFillStroke(Object args[], int numArgs);
void doPatternFill(GBool eoFill);
void doPatternStroke();
+ void doPatternText();
+ void doPatternImageMask(Object *ref, Stream *str, int width, int height,
+ GBool invert, GBool inlineImg);
void doTilingPatternFill(GfxTilingPattern *tPat,
- GBool stroke, GBool eoFill);
+ GBool stroke, GBool eoFill, GBool text);
void doShadingPatternFill(GfxShadingPattern *sPat,
- GBool stroke, GBool eoFill);
+ GBool stroke, GBool eoFill, GBool text);
void opShFill(Object args[], int numArgs);
void doFunctionShFill(GfxFunctionShading *shading);
void doFunctionShFill1(GfxFunctionShading *shading,
@@ -274,17 +319,12 @@ private:
void opMoveSetShowText(Object args[], int numArgs);
void opShowSpaceText(Object args[], int numArgs);
void doShowText(GString *s);
+ void doIncCharCount(GString *s);
// XObject operators
void opXObject(Object args[], int numArgs);
void doImage(Object *ref, Stream *str, GBool inlineImg);
void doForm(Object *str);
- void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
- GBool transpGroup = gFalse, GBool softMask = gFalse,
- GfxColorSpace *blendingColorSpace = NULL,
- GBool isolated = gFalse, GBool knockout = gFalse,
- GBool alpha = gFalse, Function *transferFunc = NULL,
- GfxColor *backdropColor = NULL);
// in-line image operators
void opBeginImage(Object args[], int numArgs);
@@ -305,6 +345,8 @@ private:
void opEndMarkedContent(Object args[], int numArgs);
void opMarkPoint(Object args[], int numArgs);
+ GfxState *saveStateStack();
+ void restoreStateStack(GfxState *oldState);
void pushResources(Dict *resDict);
void popResources();
};
diff --git a/xpdf/GfxFont.cc b/xpdf/GfxFont.cc
index 9af7efc..aa88e78 100644
--- a/xpdf/GfxFont.cc
+++ b/xpdf/GfxFont.cc
@@ -16,6 +16,11 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <math.h>
+#include <limits.h>
+#if HAVE_STD_SORT
+#include <algorithm>
+#endif
#include "gmem.h"
#include "Error.h"
#include "Object.h"
@@ -25,6 +30,7 @@
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
#include "BuiltinFontTables.h"
+#include "FoFiIdentifier.h"
#include "FoFiType1.h"
#include "FoFiType1C.h"
#include "FoFiTrueType.h"
@@ -32,17 +38,12 @@
//------------------------------------------------------------------------
-struct StdFontMapEntry {
- char *altName;
- char *properName;
+struct Base14FontMapEntry {
+ const char *altName;
+ const char *base14Name;
};
-// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
-// providing Widths and a FontDescriptor, so we munge the names into
-// the proper Base14 names. This table is from implementation note 44
-// in the PDF 1.4 spec, with some additions based on empirical
-// evidence.
-static StdFontMapEntry stdFontMap[] = {
+static Base14FontMapEntry base14FontMap[] = {
{ "Arial", "Helvetica" },
{ "Arial,Bold", "Helvetica-Bold" },
{ "Arial,BoldItalic", "Helvetica-BoldOblique" },
@@ -54,9 +55,13 @@ static StdFontMapEntry stdFontMap[] = {
{ "Arial-Italic", "Helvetica-Oblique" },
{ "Arial-ItalicMT", "Helvetica-Oblique" },
{ "ArialMT", "Helvetica" },
+ { "Courier", "Courier" },
{ "Courier,Bold", "Courier-Bold" },
{ "Courier,BoldItalic", "Courier-BoldOblique" },
{ "Courier,Italic", "Courier-Oblique" },
+ { "Courier-Bold", "Courier-Bold" },
+ { "Courier-BoldOblique", "Courier-BoldOblique" },
+ { "Courier-Oblique", "Courier-Oblique" },
{ "CourierNew", "Courier" },
{ "CourierNew,Bold", "Courier-Bold" },
{ "CourierNew,BoldItalic", "Courier-BoldOblique" },
@@ -68,14 +73,23 @@ static StdFontMapEntry stdFontMap[] = {
{ "CourierNewPS-BoldMT", "Courier-Bold" },
{ "CourierNewPS-ItalicMT", "Courier-Oblique" },
{ "CourierNewPSMT", "Courier" },
+ { "Helvetica", "Helvetica" },
{ "Helvetica,Bold", "Helvetica-Bold" },
{ "Helvetica,BoldItalic", "Helvetica-BoldOblique" },
{ "Helvetica,Italic", "Helvetica-Oblique" },
+ { "Helvetica-Bold", "Helvetica-Bold" },
{ "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
+ { "Helvetica-BoldOblique", "Helvetica-BoldOblique" },
{ "Helvetica-Italic", "Helvetica-Oblique" },
+ { "Helvetica-Oblique", "Helvetica-Oblique" },
+ { "Symbol", "Symbol" },
{ "Symbol,Bold", "Symbol" },
{ "Symbol,BoldItalic", "Symbol" },
{ "Symbol,Italic", "Symbol" },
+ { "Times-Bold", "Times-Bold" },
+ { "Times-BoldItalic", "Times-BoldItalic" },
+ { "Times-Italic", "Times-Italic" },
+ { "Times-Roman", "Times-Roman" },
{ "TimesNewRoman", "Times-Roman" },
{ "TimesNewRoman,Bold", "Times-Bold" },
{ "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
@@ -93,15 +107,66 @@ static StdFontMapEntry stdFontMap[] = {
{ "TimesNewRomanPSMT", "Times-Roman" },
{ "TimesNewRomanPSMT,Bold", "Times-Bold" },
{ "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
- { "TimesNewRomanPSMT,Italic", "Times-Italic" }
+ { "TimesNewRomanPSMT,Italic", "Times-Italic" },
+ { "ZapfDingbats", "ZapfDingbats" }
};
//------------------------------------------------------------------------
+
+// index: {fixed:0, sans-serif:4, serif:8} + bold*2 + italic
+// NB: must be in same order as psSubstFonts in PSOutputDev.cc
+static const char *base14SubstFonts[14] = {
+ "Courier",
+ "Courier-Oblique",
+ "Courier-Bold",
+ "Courier-BoldOblique",
+ "Helvetica",
+ "Helvetica-Oblique",
+ "Helvetica-Bold",
+ "Helvetica-BoldOblique",
+ "Times-Roman",
+ "Times-Italic",
+ "Times-Bold",
+ "Times-BoldItalic",
+ // the last two are never used for substitution
+ "Symbol",
+ "ZapfDingbats"
+};
+
+//------------------------------------------------------------------------
+
+static int readFromStream(void *data) {
+ return ((Stream *)data)->getChar();
+}
+
+//------------------------------------------------------------------------
+// GfxFontLoc
+//------------------------------------------------------------------------
+
+GfxFontLoc::GfxFontLoc() {
+ path = NULL;
+ fontNum = 0;
+ encoding = NULL;
+ substIdx = -1;
+}
+
+GfxFontLoc::~GfxFontLoc() {
+ if (path) {
+ delete path;
+ }
+ if (encoding) {
+ delete encoding;
+ }
+}
+
+//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
GString *nameA;
+ Ref embFontIDA;
+ GfxFontType typeA;
GfxFont *font;
Object obj1;
@@ -113,53 +178,235 @@ GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
}
obj1.free();
- // get font type
+ // get embedded font ID and font type
+ typeA = getFontType(xref, fontDict, &embFontIDA);
+
+ // create the font object
font = NULL;
- fontDict->lookup("Subtype", &obj1);
- if (obj1.isName("Type1") || obj1.isName("MMType1")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
- } else if (obj1.isName("Type1C")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
- } else if (obj1.isName("Type3")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
- } else if (obj1.isName("TrueType")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
- } else if (obj1.isName("Type0")) {
- font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
+ if (typeA < fontCIDType0) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA,
+ fontDict);
} else {
- error(-1, "Unknown font type: '%s'",
- obj1.isName() ? obj1.getName() : "???");
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
+ font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA,
+ fontDict);
}
- obj1.free();
return font;
}
-GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) {
+GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA,
+ GfxFontType typeA, Ref embFontIDA) {
ok = gFalse;
tag = new GString(tagA);
id = idA;
name = nameA;
- origName = nameA;
+ type = typeA;
+ embFontID = embFontIDA;
embFontName = NULL;
- extFontFile = NULL;
}
GfxFont::~GfxFont() {
delete tag;
- if (origName && origName != name) {
- delete origName;
- }
if (name) {
delete name;
}
if (embFontName) {
delete embFontName;
}
- if (extFontFile) {
- delete extFontFile;
+}
+
+// This function extracts three pieces of information:
+// 1. the "expected" font type, i.e., the font type implied by
+// Font.Subtype, DescendantFont.Subtype, and
+// FontDescriptor.FontFile3.Subtype
+// 2. the embedded font object ID
+// 3. the actual font type - determined by examining the embedded font
+// if there is one, otherwise equal to the expected font type
+// If the expected and actual font types don't match, a warning
+// message is printed. The expected font type is not used for
+// anything else.
+GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) {
+ GfxFontType t, expectedType;
+ FoFiIdentifierType fft;
+ Dict *fontDict2;
+ Object subtype, fontDesc, obj1, obj2, obj3, obj4;
+ GBool isType0, err;
+
+ t = fontUnknownType;
+ embID->num = embID->gen = -1;
+ err = gFalse;
+
+ fontDict->lookup("Subtype", &subtype);
+ expectedType = fontUnknownType;
+ isType0 = gFalse;
+ if (subtype.isName("Type1") || subtype.isName("MMType1")) {
+ expectedType = fontType1;
+ } else if (subtype.isName("Type1C")) {
+ expectedType = fontType1C;
+ } else if (subtype.isName("Type3")) {
+ expectedType = fontType3;
+ } else if (subtype.isName("TrueType")) {
+ expectedType = fontTrueType;
+ } else if (subtype.isName("Type0")) {
+ isType0 = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Unknown font type: '{0:s}'",
+ subtype.isName() ? subtype.getName() : "???");
+ }
+ subtype.free();
+
+ fontDict2 = fontDict;
+ if (fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == 0) {
+ error(errSyntaxWarning, -1, "Empty DescendantFonts array in font");
+ obj2.initNull();
+ } else if (obj1.arrayGet(0, &obj2)->isDict()) {
+ if (!isType0) {
+ error(errSyntaxWarning, -1, "Non-CID font with DescendantFonts array");
+ }
+ fontDict2 = obj2.getDict();
+ fontDict2->lookup("Subtype", &subtype);
+ if (subtype.isName("CIDFontType0")) {
+ if (isType0) {
+ expectedType = fontCIDType0;
+ }
+ } else if (subtype.isName("CIDFontType2")) {
+ if (isType0) {
+ expectedType = fontCIDType2;
+ }
+ }
+ subtype.free();
+ }
+ } else {
+ obj2.initNull();
}
+
+ if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) {
+ if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (expectedType != fontType1) {
+ err = gTrue;
+ }
+ }
+ obj3.free();
+ if (embID->num == -1 &&
+ fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (isType0) {
+ expectedType = fontCIDType2;
+ } else if (expectedType != fontTrueType) {
+ err = gTrue;
+ }
+ }
+ obj3.free();
+ if (embID->num == -1 &&
+ fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (obj3.fetch(xref, &obj4)->isStream()) {
+ obj4.streamGetDict()->lookup("Subtype", &subtype);
+ if (subtype.isName("Type1")) {
+ if (expectedType != fontType1) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0 : fontType1;
+ }
+ } else if (subtype.isName("Type1C")) {
+ if (expectedType == fontType1) {
+ expectedType = fontType1C;
+ } else if (expectedType != fontType1C) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0C : fontType1C;
+ }
+ } else if (subtype.isName("TrueType")) {
+ if (expectedType != fontTrueType) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType2 : fontTrueType;
+ }
+ } else if (subtype.isName("CIDFontType0C")) {
+ if (expectedType == fontCIDType0) {
+ expectedType = fontCIDType0C;
+ } else {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0C : fontType1C;
+ }
+ } else if (subtype.isName("OpenType")) {
+ if (expectedType == fontTrueType) {
+ expectedType = fontTrueTypeOT;
+ } else if (expectedType == fontType1) {
+ expectedType = fontType1COT;
+ } else if (expectedType == fontCIDType0) {
+ expectedType = fontCIDType0COT;
+ } else if (expectedType == fontCIDType2) {
+ expectedType = fontCIDType2OT;
+ } else {
+ err = gTrue;
+ }
+ } else {
+ error(errSyntaxError, -1, "Unknown font type '{0:s}'",
+ subtype.isName() ? subtype.getName() : "???");
+ }
+ subtype.free();
+ }
+ obj4.free();
+ }
+ obj3.free();
+ }
+ fontDesc.free();
+
+ t = fontUnknownType;
+ if (embID->num >= 0) {
+ obj3.initRef(embID->num, embID->gen);
+ obj3.fetch(xref, &obj4);
+ if (obj4.isStream()) {
+ obj4.streamReset();
+ fft = FoFiIdentifier::identifyStream(&readFromStream, obj4.getStream());
+ obj4.streamClose();
+ switch (fft) {
+ case fofiIdType1PFA:
+ case fofiIdType1PFB:
+ t = fontType1;
+ break;
+ case fofiIdCFF8Bit:
+ t = isType0 ? fontCIDType0C : fontType1C;
+ break;
+ case fofiIdCFFCID:
+ t = fontCIDType0C;
+ break;
+ case fofiIdTrueType:
+ case fofiIdTrueTypeCollection:
+ t = isType0 ? fontCIDType2 : fontTrueType;
+ break;
+ case fofiIdOpenTypeCFF8Bit:
+ t = isType0 ? fontCIDType0COT : fontType1COT;
+ break;
+ case fofiIdOpenTypeCFFCID:
+ t = fontCIDType0COT;
+ break;
+ default:
+ error(errSyntaxError, -1, "Embedded font file may be invalid");
+ break;
+ }
+ }
+ obj4.free();
+ obj3.free();
+ }
+
+ if (t == fontUnknownType) {
+ t = expectedType;
+ }
+
+ if (t != expectedType) {
+ err = gTrue;
+ }
+
+ if (err) {
+ error(errSyntaxWarning, -1,
+ "Mismatch between font type and embedded font file");
+ }
+
+ obj2.free();
+ obj1.free();
+
+ return t;
}
void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
@@ -170,8 +417,6 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
// assume Times-Roman by default (for substitution purposes)
flags = fontSerif;
- embFontID.num = -1;
- embFontID.gen = -1;
missingWidth = 0;
if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
@@ -189,75 +434,6 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
}
obj2.free();
- // look for embedded font file
- if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontType1;
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontTrueType && type != fontCIDType2) {
- error(-1, "Mismatch between font type and embedded font file");
- type = type == fontCIDType0 ? fontCIDType2 : fontTrueType;
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
- if (obj2.fetch(xref, &obj3)->isStream()) {
- obj3.streamGetDict()->lookup("Subtype", &obj4);
- if (obj4.isName("Type1")) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontType1;
- }
- } else if (obj4.isName("Type1C")) {
- embFontID = obj2.getRef();
- if (type != fontType1 && type != fontType1C) {
- error(-1, "Mismatch between font type and embedded font file");
- }
- type = fontType1C;
- } else if (obj4.isName("TrueType")) {
- embFontID = obj2.getRef();
- if (type != fontTrueType) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontTrueType;
- }
- } else if (obj4.isName("CIDFontType0C")) {
- embFontID = obj2.getRef();
- if (type != fontCIDType0) {
- 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() : "???");
- }
- obj4.free();
- }
- obj3.free();
- }
- obj2.free();
-
// look for MissingWidth
obj1.dictLookup("MissingWidth", &obj2);
if (obj2.isNum()) {
@@ -269,8 +445,13 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
obj1.dictLookup("Ascent", &obj2);
if (obj2.isNum()) {
t = 0.001 * obj2.getNum();
- // some broken font descriptors set ascent and descent to 0
- if (t != 0) {
+ // some broken font descriptors specify a negative ascent
+ if (t < 0) {
+ t = -t;
+ }
+ // some broken font descriptors set ascent and descent to 0;
+ // others set it to ridiculous values (e.g., 32768)
+ if (t != 0 && t < 3) {
ascent = t;
}
}
@@ -278,14 +459,14 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
obj1.dictLookup("Descent", &obj2);
if (obj2.isNum()) {
t = 0.001 * obj2.getNum();
+ // some broken font descriptors specify a positive descent
+ if (t > 0) {
+ t = -t;
+ }
// some broken font descriptors set ascent and descent to 0
- if (t != 0) {
+ if (t != 0 && t > -3) {
descent = t;
}
- // some broken font descriptors specify a positive descent
- if (descent > 0) {
- descent = -descent;
- }
}
obj2.free();
@@ -330,37 +511,280 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
return ctu;
}
-void GfxFont::findExtFontFile() {
- static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
- static char *ttExts[] = { ".ttf", NULL };
+GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
+ GfxFontLoc *fontLoc;
+ SysFontType sysFontType;
+ GString *path, *base14Name, *substName;
+ PSFontParam16 *psFont16;
+ Object refObj, embFontObj;
+ int substIdx, fontNum;
+ GBool embed;
- if (name) {
- if (type == fontType1) {
- extFontFile = globalParams->findFontFile(name, type1Exts);
- } else if (type == fontTrueType) {
- extFontFile = globalParams->findFontFile(name, ttExts);
+ if (type == fontType3) {
+ return NULL;
+ }
+
+ //----- embedded font
+ if (embFontID.num >= 0) {
+ embed = gTrue;
+ refObj.initRef(embFontID.num, embFontID.gen);
+ refObj.fetch(xref, &embFontObj);
+ if (!embFontObj.isStream()) {
+ error(errSyntaxError, -1, "Embedded font object is wrong type");
+ embed = gFalse;
+ }
+ embFontObj.free();
+ refObj.free();
+ if (embed) {
+ if (ps) {
+ switch (type) {
+ case fontType1:
+ case fontType1C:
+ case fontType1COT:
+ embed = globalParams->getPSEmbedType1();
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ embed = globalParams->getPSEmbedTrueType();
+ break;
+ case fontCIDType0C:
+ case fontCIDType0COT:
+ embed = globalParams->getPSEmbedCIDPostScript();
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ embed = globalParams->getPSEmbedCIDTrueType();
+ break;
+ default:
+ break;
+ }
+ }
+ if (embed) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocEmbedded;
+ fontLoc->fontType = type;
+ fontLoc->embFontID = embFontID;
+ return fontLoc;
+ }
}
}
+
+ //----- PS passthrough
+ if (ps && !isCIDFont() && globalParams->getPSFontPassthrough()) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = name->copy();
+ return fontLoc;
+ }
+
+ //----- PS resident Base-14 font
+ if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = new GString(((Gfx8BitFont *)this)->base14->base14Name);
+ return fontLoc;
+ }
+
+ //----- external font file (fontFile, fontDir)
+ if ((path = globalParams->findFontFile(name))) {
+ if ((fontLoc = getExternalFont(path, isCIDFont()))) {
+ return fontLoc;
+ }
+ }
+
+ //----- external font file for Base-14 font
+ if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
+ base14Name = new GString(((Gfx8BitFont *)this)->base14->base14Name);
+ if ((path = globalParams->findFontFile(base14Name))) {
+ if ((fontLoc = getExternalFont(path, gFalse))) {
+ delete base14Name;
+ return fontLoc;
+ }
+ }
+ delete base14Name;
+ }
+
+ //----- system font
+ if ((path = globalParams->findSystemFontFile(name, &sysFontType,
+ &fontNum))) {
+ if (isCIDFont()) {
+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontCIDType2;
+ fontLoc->path = path;
+ fontLoc->fontNum = fontNum;
+ return fontLoc;
+ }
+ } else {
+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontTrueType;
+ fontLoc->path = path;
+ return fontLoc;
+ } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = path;
+ fontLoc->fontNum = fontNum;
+ return fontLoc;
+ }
+ }
+ delete path;
+ }
+
+ if (!isCIDFont()) {
+
+ //----- 8-bit PS resident font
+ if (ps) {
+ if ((path = globalParams->getPSResidentFont(name))) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = path;
+ return fontLoc;
+ }
+ }
+
+ //----- 8-bit font substitution
+ if (flags & fontFixedWidth) {
+ substIdx = 0;
+ } else if (flags & fontSerif) {
+ substIdx = 8;
+ } else {
+ substIdx = 4;
+ }
+ if (isBold()) {
+ substIdx += 2;
+ }
+ if (isItalic()) {
+ substIdx += 1;
+ }
+ substName = new GString(base14SubstFonts[substIdx]);
+ if (ps) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
+ base14SubstFonts[substIdx], name);
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = substName;
+ fontLoc->substIdx = substIdx;
+ return fontLoc;
+ } else {
+ path = globalParams->findFontFile(substName);
+ delete substName;
+ if (path) {
+ if ((fontLoc = getExternalFont(path, gFalse))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
+ base14SubstFonts[substIdx], name);
+ fontLoc->substIdx = substIdx;
+ return fontLoc;
+ }
+ }
+ }
+
+ // failed to find a substitute font
+ return NULL;
+ }
+
+ //----- 16-bit PS resident font
+ if (ps && ((psFont16 = globalParams->getPSResidentFont16(
+ name,
+ ((GfxCIDFont *)this)->getWMode())))) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontCIDType0; // this is not used
+ fontLoc->path = psFont16->psFontName->copy();
+ fontLoc->encoding = psFont16->encoding->copy();
+ fontLoc->wMode = psFont16->wMode;
+ return fontLoc;
+ }
+ if (ps && ((psFont16 = globalParams->getPSResidentFontCC(
+ ((GfxCIDFont *)this)->getCollection(),
+ ((GfxCIDFont *)this)->getWMode())))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
+ psFont16->psFontName, name);
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontCIDType0; // this is not used
+ fontLoc->path = psFont16->psFontName->copy();
+ fontLoc->encoding = psFont16->encoding->copy();
+ fontLoc->wMode = psFont16->wMode;
+ return fontLoc;
+ }
+
+ //----- CID font substitution
+ if ((path = globalParams->findCCFontFile(
+ ((GfxCIDFont *)this)->getCollection()))) {
+ if ((fontLoc = getExternalFont(path, gTrue))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
+ fontLoc->path, name);
+ return fontLoc;
+ }
+ }
+
+ // failed to find a substitute font
+ return NULL;
}
-char *GfxFont::readExtFontFile(int *len) {
- FILE *f;
- char *buf;
+GfxFontLoc *GfxFont::locateBase14Font(GString *base14Name) {
+ GString *path;
- if (!(f = fopen(extFontFile->getCString(), "rb"))) {
- error(-1, "External font file '%s' vanished", extFontFile->getCString());
+ path = globalParams->findFontFile(base14Name);
+ if (!path) {
return NULL;
}
- fseek(f, 0, SEEK_END);
- *len = (int)ftell(f);
- fseek(f, 0, SEEK_SET);
- buf = (char *)gmalloc(*len);
- if ((int)fread(buf, 1, *len, f) != *len) {
- error(-1, "Error reading external font file '%s'",
- extFontFile->getCString());
+ return getExternalFont(path, gFalse);
+}
+
+GfxFontLoc *GfxFont::getExternalFont(GString *path, GBool cid) {
+ FoFiIdentifierType fft;
+ GfxFontType fontType;
+ GfxFontLoc *fontLoc;
+
+ fft = FoFiIdentifier::identifyFile(path->getCString());
+ switch (fft) {
+ case fofiIdType1PFA:
+ case fofiIdType1PFB:
+ fontType = fontType1;
+ break;
+ case fofiIdCFF8Bit:
+ fontType = fontType1C;
+ break;
+ case fofiIdCFFCID:
+ fontType = fontCIDType0C;
+ break;
+ case fofiIdTrueType:
+ case fofiIdTrueTypeCollection:
+ fontType = cid ? fontCIDType2 : fontTrueType;
+ break;
+ case fofiIdOpenTypeCFF8Bit:
+ fontType = fontType1COT;
+ break;
+ case fofiIdOpenTypeCFFCID:
+ fontType = fontCIDType0COT;
+ break;
+ case fofiIdUnknown:
+ case fofiIdError:
+ default:
+ fontType = fontUnknownType;
+ break;
+ }
+ if (fontType == fontUnknownType ||
+ (cid ? (fontType < fontCIDType0)
+ : (fontType >= fontCIDType0))) {
+ delete path;
+ return NULL;
}
- fclose(f);
- return buf;
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontType;
+ fontLoc->path = path;
+ return fontLoc;
}
char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
@@ -373,7 +797,7 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
obj1.initRef(embFontID.num, embFontID.gen);
obj1.fetch(xref, &obj2);
if (!obj2.isStream()) {
- error(-1, "Embedded font file is not a stream");
+ error(errSyntaxError, -1, "Embedded font file is not a stream");
obj2.free();
obj1.free();
embFontID.num = -1;
@@ -386,6 +810,10 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
str->reset();
while ((c = str->getChar()) != EOF) {
if (i == size) {
+ if (size > INT_MAX - 4096) {
+ error(errSyntaxError, -1, "Embedded font file is too large");
+ break;
+ }
size += 4096;
buf = (char *)grealloc(buf, size);
}
@@ -405,12 +833,12 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
//------------------------------------------------------------------------
Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- GfxFontType typeA, Dict *fontDict):
- GfxFont(tagA, idA, nameA)
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
+ GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
GString *name2;
BuiltinFont *builtinFont;
- char **baseEnc;
+ const char **baseEnc;
GBool baseEncFromFontFile;
char *buf;
int len;
@@ -428,11 +856,11 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
Object obj1, obj2, obj3;
int n, i, a, b, m;
- type = typeA;
ctu = NULL;
// do font name substitution for various aliases of the Base 14 font
// names
+ base14 = NULL;
if (name) {
name2 = name->copy();
i = 0;
@@ -444,27 +872,27 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
}
a = 0;
- b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
- // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName
+ b = sizeof(base14FontMap) / sizeof(Base14FontMapEntry);
+ // invariant: base14FontMap[a].altName <= name2 < base14FontMap[b].altName
while (b - a > 1) {
m = (a + b) / 2;
- if (name2->cmp(stdFontMap[m].altName) >= 0) {
+ if (name2->cmp(base14FontMap[m].altName) >= 0) {
a = m;
} else {
b = m;
}
}
- if (!name2->cmp(stdFontMap[a].altName)) {
- name = new GString(stdFontMap[a].properName);
+ if (!name2->cmp(base14FontMap[a].altName)) {
+ base14 = &base14FontMap[a];
}
delete name2;
}
// is it a built-in font?
builtinFont = NULL;
- if (name) {
+ if (base14) {
for (i = 0; i < nBuiltinFonts; ++i) {
- if (!name->cmp(builtinFonts[i].name)) {
+ if (!strcmp(base14->base14Name, builtinFonts[i].name)) {
builtinFont = &builtinFonts[i];
break;
}
@@ -499,9 +927,6 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
fontBBox[3] = 0.001 * builtinFont->bbox[3];
}
- // look for an external font file
- findExtFontFile();
-
// get font matrix
fontMat[0] = fontMat[3] = 1;
fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
@@ -527,7 +952,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
obj1.free();
if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
- error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
+ error(errSyntaxError, -1,
+ "Missing or invalid CharProcs dictionary in Type 3 font");
charProcs.free();
}
if (!fontDict->lookup("Resources", &resources)->isDict()) {
@@ -581,54 +1007,45 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
baseEnc = winAnsiEncoding;
}
- // check embedded or external font file for base encoding
+ // check embedded font file for base encoding
// (only for Type 1 fonts - trying to get an encoding out of a
// TrueType font is a losing proposition)
ffT1 = NULL;
ffT1C = NULL;
buf = NULL;
- if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1 = FoFiType1::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1 = FoFiType1::make(buf, len);
- }
- if (ffT1) {
- if (ffT1->getName()) {
- if (embFontName) {
- delete embFontName;
+ if (type == fontType1 && embFontID.num >= 0) {
+ if ((buf = readEmbFontFile(xref, &len))) {
+ if ((ffT1 = FoFiType1::make(buf, len))) {
+ if (ffT1->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GString(ffT1->getName());
+ }
+ if (!baseEnc) {
+ baseEnc = (const char **)ffT1->getEncoding();
+ baseEncFromFontFile = gTrue;
}
- embFontName = new GString(ffT1->getName());
- }
- if (!baseEnc) {
- baseEnc = ffT1->getEncoding();
- baseEncFromFontFile = gTrue;
}
+ gfree(buf);
}
- } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1C = FoFiType1C::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1C = FoFiType1C::make(buf, len);
- }
- if (ffT1C) {
- if (ffT1C->getName()) {
- if (embFontName) {
- delete embFontName;
+ } else if (type == fontType1C && embFontID.num >= 0) {
+ if ((buf = readEmbFontFile(xref, &len))) {
+ if ((ffT1C = FoFiType1C::make(buf, len))) {
+ if (ffT1C->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GString(ffT1C->getName());
+ }
+ if (!baseEnc) {
+ baseEnc = (const char **)ffT1C->getEncoding();
+ baseEncFromFontFile = gTrue;
}
- embFontName = new GString(ffT1C->getName());
- }
- if (!baseEnc) {
- baseEnc = ffT1C->getEncoding();
- baseEncFromFontFile = gTrue;
}
+ gfree(buf);
}
}
- if (buf) {
- gfree(buf);
- }
// get default base encoding
if (!baseEnc) {
@@ -644,7 +1061,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// copy the base encoding
for (i = 0; i < 256; ++i) {
- enc[i] = baseEnc[i];
+ enc[i] = (char *)baseEnc[i];
if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
enc[i] = copyString(baseEnc[i]);
}
@@ -654,11 +1071,10 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// T1C->T1 conversion (since the 'seac' operator depends on having
// the accents in the encoding), so we fill in any gaps from
// StandardEncoding
- if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
- baseEncFromFontFile) {
+ if (type == fontType1C && embFontID.num >= 0 && baseEncFromFontFile) {
for (i = 0; i < 256; ++i) {
if (!enc[i] && standardEncoding[i]) {
- enc[i] = standardEncoding[i];
+ enc[i] = (char *)standardEncoding[i];
encFree[i] = gFalse;
}
}
@@ -684,7 +1100,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
++code;
} else {
- error(-1, "Wrong type in font encoding resource differences (%s)",
+ error(errSyntaxError, -1,
+ "Wrong type in font encoding resource differences ({0:s})",
obj3.getTypeName());
}
obj3.free();
@@ -734,14 +1151,21 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
// pass 2: try to fill in the missing chars, looking for names of
- // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
- // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
- // decimal digits
+ // any of the following forms:
+ // - 'xx'
+ // - 'Axx'
+ // - 'nn'
+ // - 'Ann'
+ // - 'ABnn'
+ // - 'unixxxx' (possibly followed by garbage - some Arabic files
+ // use 'uni0628.medi', etc.)
+ // where 'A' and 'B' are any letters, 'xx' is two hex digits, 'xxxx'
+ // is four hex digits, and 'nn' is 2-4 decimal digits
if (missing && globalParams->getMapNumericCharNames()) {
for (code = 0; code < 256; ++code) {
if ((charName = enc[code]) && !toUnicode[code] &&
strcmp(charName, ".notdef")) {
- n = strlen(charName);
+ n = (int)strlen(charName);
code2 = -1;
if (hex && n == 3 && isalpha(charName[0]) &&
isxdigit(charName[1]) && isxdigit(charName[2])) {
@@ -758,8 +1182,13 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
} else if (n >= 4 && n <= 6 &&
isdigit(charName[2]) && isdigit(charName[3])) {
code2 = atoi(charName+2);
+ } else if (n >= 7 && charName[0] == 'u' && charName[1] == 'n' &&
+ charName[2] == 'i' &&
+ isxdigit(charName[3]) && isxdigit(charName[4]) &&
+ isxdigit(charName[5]) && isxdigit(charName[6])) {
+ sscanf(charName + 3, "%x", &code2);
}
- if (code2 >= 0 && code2 <= 0xff) {
+ if (code2 >= 0 && code2 <= 0xffff) {
toUnicode[code] = (Unicode)code2;
}
}
@@ -835,7 +1264,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj1.arrayGet(code - firstChar, &obj2);
if (obj2.isNum()) {
widths[code] = obj2.getNum() * mul;
- if (widths[code] != widths[firstChar]) {
+ if (fabs(widths[code] - widths[firstChar]) > 0.00001) {
flags &= ~fontFixedWidth;
}
}
@@ -924,8 +1353,8 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
return ctu;
}
-Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
- Gushort *map;
+int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
+ int *map;
int cmapPlatform, cmapEncoding;
int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
GBool useMacRoman, useUnicode;
@@ -933,7 +1362,7 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
Unicode u;
int code, i, n;
- map = (Gushort *)gmallocn(256, sizeof(Gushort));
+ map = (int *)gmallocn(256, sizeof(int));
for (i = 0; i < 256; ++i) {
map[i] = 0;
}
@@ -945,9 +1374,10 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
// TrueType font has a Macintosh Roman cmap, use it, and
// reverse map the char names through MacRomanEncoding to
// get char codes.
- // 1b. If the TrueType font has a Microsoft Unicode cmap or a
- // non-Microsoft Unicode cmap, use it, and use the Unicode
- // indexes, not the char codes.
+ // 1b. If the PDF font is not symbolic or the PDF font is not
+ // embedded, and the TrueType font has a Microsoft Unicode
+ // cmap or a non-Microsoft Unicode cmap, use it, and use the
+ // Unicode indexes, not the char codes.
// 1c. If the PDF font is symbolic and the TrueType font has a
// Microsoft Symbol cmap, use it, and use char codes
// directly (possibly with an offset of 0xf000).
@@ -983,7 +1413,8 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
if (usesMacRomanEnc && macRomanCmap >= 0) {
cmap = macRomanCmap;
useMacRoman = gTrue;
- } else if (unicodeCmap >= 0) {
+ } else if ((!(flags & fontSymbolic) || embFontID.num < 0) &&
+ unicodeCmap >= 0) {
cmap = unicodeCmap;
useUnicode = gTrue;
} else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
@@ -1010,6 +1441,8 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
if ((code = globalParams->getMacRomanCharCode(charName))) {
map[i] = ff->mapCodeToGID(cmap, code);
}
+ } else {
+ map[i] = -1;
}
}
@@ -1020,6 +1453,8 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
(u = globalParams->mapNameToUnicode(charName))) ||
(n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
map[i] = ff->mapCodeToGID(cmap, u);
+ } else {
+ map[i] = -1;
}
}
@@ -1035,8 +1470,8 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
// try the TrueType 'post' table to handle any unmapped characters
for (i = 0; i < 256; ++i) {
- if (!map[i] && (charName = enc[i])) {
- map[i] = (Gushort)(int)ff->mapNameToGID(charName);
+ if (map[i] <= 0 && (charName = enc[i])) {
+ map[i] = ff->mapNameToGID(charName);
}
}
@@ -1064,6 +1499,24 @@ Dict *Gfx8BitFont::getResources() {
// GfxCIDFont
//------------------------------------------------------------------------
+#if HAVE_STD_SORT
+
+struct cmpWidthExcepFunctor {
+ bool operator()(const GfxFontCIDWidthExcep &w1,
+ const GfxFontCIDWidthExcep &w2) {
+ return w1.first < w2.first;
+ }
+};
+
+struct cmpWidthExcepVFunctor {
+ bool operator()(const GfxFontCIDWidthExcepV &w1,
+ const GfxFontCIDWidthExcepV &w2) {
+ return w1.first < w2.first;
+ }
+};
+
+#else // HAVE_STD_SORT
+
static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcep *)w1)->first -
((GfxFontCIDWidthExcep *)w2)->first;
@@ -1074,12 +1527,13 @@ static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
((GfxFontCIDWidthExcepV *)w2)->first;
}
+#endif
+
GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- Dict *fontDict):
- GfxFont(tagA, idA, nameA)
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
+ GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
Dict *desFontDict;
- GString *collection, *cMapName;
Object desFontDictObj;
Object obj1, obj2, obj3, obj4, obj5, obj6;
CharCodeToUnicode *utu;
@@ -1091,8 +1545,10 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
ascent = 0.95;
descent = -0.35;
fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
+ collection = NULL;
cMap = NULL;
ctu = NULL;
+ ctuUsesCharCode = gTrue;
widths.defWidth = 1.0;
widths.defHeight = -1.0;
widths.defVY = 0.880;
@@ -1104,52 +1560,38 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
cidToGIDLen = 0;
// get the descendant font
- if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
- error(-1, "Missing DescendantFonts entry in Type 0 font");
+ if (!fontDict->lookup("DescendantFonts", &obj1)->isArray() ||
+ obj1.arrayGetLength() == 0) {
+ error(errSyntaxError, -1,
+ "Missing or empty DescendantFonts entry in Type 0 font");
obj1.free();
+
goto err1;
}
if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
- error(-1, "Bad descendant font in Type 0 font");
- goto err3;
+ error(errSyntaxError, -1, "Bad descendant font in Type 0 font");
+ goto err2;
}
obj1.free();
desFontDict = desFontDictObj.getDict();
- // font type
- if (!desFontDict->lookup("Subtype", &obj1)) {
- error(-1, "Missing Subtype entry in Type 0 descendant font");
- goto err3;
- }
- if (obj1.isName("CIDFontType0")) {
- type = fontCIDType0;
- } else if (obj1.isName("CIDFontType2")) {
- type = fontCIDType2;
- } else {
- error(-1, "Unknown Type 0 descendant font type '%s'",
- obj1.isName() ? obj1.getName() : "???");
- goto err3;
- }
- obj1.free();
-
// get info from font descriptor
readFontDescriptor(xref, desFontDict);
- // look for an external font file
- findExtFontFile();
-
//----- encoding info -----
// char collection
if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
- error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
- goto err3;
+ error(errSyntaxError, -1,
+ "Missing CIDSystemInfo dictionary in Type 0 descendant font");
+ goto err2;
}
obj1.dictLookup("Registry", &obj2);
obj1.dictLookup("Ordering", &obj3);
if (!obj2.isString() || !obj3.isString()) {
- error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
- goto err4;
+ error(errSyntaxError, -1,
+ "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
+ goto err3;
}
collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
obj3.free();
@@ -1158,19 +1600,18 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// look for a ToUnicode CMap
if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
-
- // the "Adobe-Identity" and "Adobe-UCS" collections don't have
- // cidToUnicode files
- if (collection->cmp("Adobe-Identity") &&
- collection->cmp("Adobe-UCS")) {
-
- // look for a user-supplied .cidToUnicode file
- if (!(ctu = globalParams->getCIDToUnicode(collection))) {
- error(-1, "Unknown character collection '%s'",
- collection->getCString());
- // fall-through, assuming the Identity mapping -- this appears
- // to match Adobe's behavior
- }
+ ctuUsesCharCode = gFalse;
+
+ // use an identity mapping for the "Adobe-Identity" and
+ // "Adobe-UCS" collections
+ if (!collection->cmp("Adobe-Identity") ||
+ !collection->cmp("Adobe-UCS")) {
+ ctu = CharCodeToUnicode::makeIdentityMapping();
+
+ // look for a user-supplied .cidToUnicode file
+ } else if (!(ctu = globalParams->getCIDToUnicode(collection))) {
+ error(errSyntaxError, -1,
+ "Unknown character collection '{0:t}'", collection);
}
}
@@ -1193,43 +1634,35 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
// encoding (i.e., CMap)
- //~ need to handle a CMap stream here
- //~ also need to deal with the UseCMap entry in the stream dict
- if (!fontDict->lookup("Encoding", &obj1)->isName()) {
- error(-1, "Missing or invalid Encoding entry in Type 0 font");
- delete collection;
- goto err3;
+ if (fontDict->lookup("Encoding", &obj1)->isNull()) {
+ error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font");
+ goto err2;
}
- cMapName = new GString(obj1.getName());
- obj1.free();
- if (!(cMap = globalParams->getCMap(collection, cMapName))) {
- error(-1, "Unknown CMap '%s' for character collection '%s'",
- cMapName->getCString(), collection->getCString());
- delete collection;
- delete cMapName;
+ if (!(cMap = CMap::parse(NULL, collection, &obj1))) {
goto err2;
}
- delete collection;
- delete cMapName;
+ obj1.free();
- // CIDToGIDMap (for embedded TrueType fonts)
- if (type == fontCIDType2) {
+ // CIDToGIDMap
+ // (the PDF spec only allows these for TrueType fonts, but Acrobat
+ // apparently also allows them for OpenType CFF fonts)
+ if (type == fontCIDType2 || type == fontCIDType0COT) {
desFontDict->lookup("CIDToGIDMap", &obj1);
if (obj1.isStream()) {
cidToGIDLen = 0;
i = 64;
- cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort));
+ cidToGID = (int *)gmallocn(i, sizeof(int));
obj1.streamReset();
while ((c1 = obj1.streamGetChar()) != EOF &&
(c2 = obj1.streamGetChar()) != EOF) {
if (cidToGIDLen == i) {
i *= 2;
- cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort));
+ cidToGID = (int *)greallocn(cidToGID, i, sizeof(int));
}
- cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
+ cidToGID[cidToGIDLen++] = (c1 << 8) + c2;
}
} else if (!obj1.isName("Identity") && !obj1.isNull()) {
- error(-1, "Invalid CIDToGIDMap entry in CID font");
+ error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font");
}
obj1.free();
}
@@ -1262,7 +1695,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
++widths.nExceps;
} else {
- error(-1, "Bad widths array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths array in Type 0 font");
}
obj4.free();
i += 3;
@@ -1282,20 +1715,25 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
++j;
++widths.nExceps;
} else {
- error(-1, "Bad widths array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths array in Type 0 font");
}
obj4.free();
}
i += 2;
} else {
- error(-1, "Bad widths array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths array in Type 0 font");
++i;
}
obj3.free();
obj2.free();
}
+#if HAVE_STD_SORT
+ std::sort(widths.exceps, widths.exceps + widths.nExceps,
+ cmpWidthExcepFunctor());
+#else
qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
&cmpWidthExcep);
+#endif
}
obj1.free();
@@ -1337,7 +1775,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
++widths.nExcepsV;
} else {
- error(-1, "Bad widths (W2) array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
}
obj6.free();
obj5.free();
@@ -1356,15 +1794,15 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
if (obj3.arrayGet(k, &obj4)->isNum() &&
obj3.arrayGet(k+1, &obj5)->isNum() &&
obj3.arrayGet(k+2, &obj6)->isNum()) {
- widths.excepsV[widths.nExceps].first = j;
- widths.excepsV[widths.nExceps].last = j;
- widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
- widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001;
- widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001;
+ widths.excepsV[widths.nExcepsV].first = j;
+ widths.excepsV[widths.nExcepsV].last = j;
+ widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
+ widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
+ widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
++j;
++widths.nExcepsV;
} else {
- error(-1, "Bad widths (W2) array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
}
obj6.free();
obj5.free();
@@ -1372,14 +1810,19 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
i += 2;
} else {
- error(-1, "Bad widths (W2) array in Type 0 font");
+ error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
++i;
}
obj3.free();
obj2.free();
}
+#if HAVE_STD_SORT
+ std::sort(widths.excepsV, widths.excepsV + widths.nExcepsV,
+ cmpWidthExcepVFunctor());
+#else
qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
&cmpWidthExcepV);
+#endif
}
obj1.free();
@@ -1387,17 +1830,19 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
ok = gTrue;
return;
- err4:
+ err3:
obj3.free();
obj2.free();
- err3:
- obj1.free();
err2:
+ obj1.free();
desFontDictObj.free();
err1:;
}
GfxCIDFont::~GfxCIDFont() {
+ if (collection) {
+ delete collection;
+ }
if (cMap) {
cMap->decRefCnt();
}
@@ -1415,6 +1860,7 @@ int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
double *dx, double *dy, double *ox, double *oy) {
CID cid;
+ CharCode c;
double w, h, vx, vy;
int n, a, b, m;
@@ -1425,12 +1871,16 @@ int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
return 1;
}
- *code = (CharCode)(cid = cMap->getCID(s, len, &n));
+ *code = (CharCode)(cid = cMap->getCID(s, len, &c, &n));
if (ctu) {
- *uLen = ctu->mapToUnicode(cid, u, uSize);
+ *uLen = ctu->mapToUnicode(ctuUsesCharCode ? c : cid, u, uSize);
} else {
*uLen = 0;
}
+ if (!*uLen && uSize >= 1 && globalParams->getMapUnknownCharNames()) {
+ u[0] = *code;
+ *uLen = 1;
+ }
// horizontal
if (cMap->getWMode() == 0) {
@@ -1537,7 +1987,7 @@ GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
fonts[i] = NULL;
}
} else {
- error(-1, "font resource is not a dictionary");
+ error(errSyntaxError, -1, "font resource is not a dictionary");
fonts[i] = NULL;
}
obj1.free();
diff --git a/xpdf/GfxFont.h b/xpdf/GfxFont.h
index d076692..db45ef0 100644
--- a/xpdf/GfxFont.h
+++ b/xpdf/GfxFont.h
@@ -25,6 +25,7 @@ class CMap;
class CharCodeToUnicode;
class FoFiTrueType;
struct GfxFontCIDWidths;
+struct Base14FontMapEntry;
//------------------------------------------------------------------------
// GfxFontType
@@ -76,6 +77,41 @@ struct GfxFontCIDWidths {
};
//------------------------------------------------------------------------
+// GfxFontLoc
+//------------------------------------------------------------------------
+
+enum GfxFontLocType {
+ gfxFontLocEmbedded, // font embedded in PDF file
+ gfxFontLocExternal, // external font file
+ gfxFontLocResident // font resident in PS printer
+};
+
+class GfxFontLoc {
+public:
+
+ GfxFontLoc();
+ ~GfxFontLoc();
+
+ GfxFontLocType locType;
+ GfxFontType fontType;
+ Ref embFontID; // embedded stream obj ID
+ // (if locType == gfxFontLocEmbedded)
+ GString *path; // font file path
+ // (if locType == gfxFontLocExternal)
+ // PS font name
+ // (if locType == gfxFontLocResident)
+ int fontNum; // for TrueType collections
+ // (if locType == gfxFontLocExternal)
+ GString *encoding; // PS font encoding, only for 16-bit fonts
+ // (if locType == gfxFontLocResident)
+ int wMode; // writing mode, only for 16-bit fonts
+ // (if locType == gfxFontLocResident)
+ int substIdx; // substitute font index
+ // (if locType == gfxFontLocExternal,
+ // and a Base-14 substitution was made)
+};
+
+//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
@@ -91,7 +127,8 @@ public:
// Build a GfxFont object.
static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
- GfxFont(char *tagA, Ref idA, GString *nameA);
+ GfxFont(char *tagA, Ref idA, GString *nameA,
+ GfxFontType typeA, Ref embFontIDA);
virtual ~GfxFont();
@@ -106,12 +143,9 @@ public:
// Does this font match the tag?
GBool matches(char *tagA) { return !tag->cmp(tagA); }
- // Get base font name.
- GString *getName() { return name; }
-
// Get the original font name (ignornig any munging that might have
// been done to map to a canonical Base-14 font name).
- GString *getOrigName() { return origName; }
+ GString *getName() { return name; }
// Get font type.
GfxFontType getType() { return type; }
@@ -126,10 +160,6 @@ public:
// NULL if there is no embedded font.
GString *getEmbeddedFontName() { return embFontName; }
- // Get the name of the external font file. Returns NULL if there
- // is no external font file.
- GString *getExtFontFile() { return extFontFile; }
-
// Get font descriptor flags.
int getFlags() { return flags; }
GBool isFixedWidth() { return flags & fontFixedWidth; }
@@ -151,8 +181,14 @@ public:
// Return the writing mode (0=horizontal, 1=vertical).
virtual int getWMode() { return 0; }
- // Read an external or embedded font file into a buffer.
- char *readExtFontFile(int *len);
+ // Locate the font file for this font. If <ps> is true, includes PS
+ // printer-resident fonts. Returns NULL on failure.
+ GfxFontLoc *locateFont(XRef *xref, GBool ps);
+
+ // Locate a Base-14 font file for a specified font name.
+ static GfxFontLoc *locateBase14Font(GString *base14Name);
+
+ // Read an embedded font file into a buffer.
char *readEmbFontFile(XRef *xref, int *len);
// Get the next char from a string <s> of <len> bytes, returning the
@@ -167,22 +203,21 @@ public:
protected:
+ static GfxFontType getFontType(XRef *xref, Dict *fontDict, Ref *embID);
void readFontDescriptor(XRef *xref, Dict *fontDict);
CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits,
CharCodeToUnicode *ctu);
- void findExtFontFile();
+ static GfxFontLoc *getExternalFont(GString *path, GBool cid);
GString *tag; // PDF font tag
Ref id; // reference (used as unique ID)
GString *name; // font name
- GString *origName; // original font name
GfxFontType type; // type of font
int flags; // font descriptor flags
GString *embFontName; // name of embedded font
Ref embFontID; // ref to embedded font file stream
- GString *extFontFile; // external font file name
- double fontMat[6]; // font matrix (Type 3 only)
- double fontBBox[4]; // font bounding box (Type 3 only)
+ double fontMat[6]; // font matrix
+ double fontBBox[4]; // font bounding box
double missingWidth; // "default" width
double ascent; // max height above baseline
double descent; // max depth below baseline
@@ -197,7 +232,7 @@ class Gfx8BitFont: public GfxFont {
public:
Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- GfxFontType typeA, Dict *fontDict);
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual ~Gfx8BitFont();
@@ -225,7 +260,7 @@ public:
// Return a char code-to-GID mapping for the provided font file.
// (This is only useful for TrueType fonts.)
- Gushort *getCodeToGIDMap(FoFiTrueType *ff);
+ int *getCodeToGIDMap(FoFiTrueType *ff);
// Return the Type 3 CharProc dictionary, or NULL if none.
Dict *getCharProcs();
@@ -238,6 +273,7 @@ public:
private:
+ Base14FontMapEntry *base14; // for Base-14 fonts only; NULL otherwise
char *enc[256]; // char code --> char name
char encFree[256]; // boolean for each char name: if set,
// the string is malloc'ed
@@ -247,6 +283,8 @@ private:
double widths[256]; // character widths
Object charProcs; // Type 3 CharProcs dictionary
Object resources; // Type 3 Resources dictionary
+
+ friend class GfxFont;
};
//------------------------------------------------------------------------
@@ -257,7 +295,7 @@ class GfxCIDFont: public GfxFont {
public:
GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- Dict *fontDict);
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual ~GfxCIDFont();
@@ -278,15 +316,18 @@ public:
// Return the CID-to-GID mapping table. These should only be called
// if type is fontCIDType2.
- Gushort *getCIDToGID() { return cidToGID; }
+ int *getCIDToGID() { return cidToGID; }
int getCIDToGIDLen() { return cidToGIDLen; }
private:
+ GString *collection; // collection name
CMap *cMap; // char code --> CID
- CharCodeToUnicode *ctu; // CID --> Unicode
+ CharCodeToUnicode *ctu; // CID/char code --> Unicode
+ GBool ctuUsesCharCode; // true: ctu maps char code to Unicode;
+ // false: ctu maps CID to Unicode
GfxFontCIDWidths widths; // character widths
- Gushort *cidToGID; // CID --> GID mapping (for embedded
+ int *cidToGID; // CID --> GID mapping (for embedded
// TrueType fonts)
int cidToGIDLen;
};
diff --git a/xpdf/GfxState.cc b/xpdf/GfxState.cc
index 67b4f6f..cf5e7c2 100644
--- a/xpdf/GfxState.cc
+++ b/xpdf/GfxState.cc
@@ -24,6 +24,13 @@
//------------------------------------------------------------------------
+// Max depth of nested color spaces. This is used to catch infinite
+// loops in the color space object structure.
+#define colorSpaceRecursionLimit 8
+
+
+//------------------------------------------------------------------------
+
static inline GfxColorComp clip01(GfxColorComp x) {
return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
}
@@ -35,7 +42,7 @@ static inline double clip01(double x) {
//------------------------------------------------------------------------
struct GfxBlendModeInfo {
- char *name;
+ const char *name;
GfxBlendMode mode;
};
@@ -66,7 +73,7 @@ static GfxBlendModeInfo gfxBlendModeNames[] = {
// NB: This must match the GfxColorSpaceMode enum defined in
// GfxState.h
-static char *gfxColorSpaceModeNames[] = {
+static const char *gfxColorSpaceModeNames[] = {
"DeviceGray",
"CalGray",
"DeviceRGB",
@@ -82,20 +89,26 @@ static char *gfxColorSpaceModeNames[] = {
#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
+
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
GfxColorSpace::GfxColorSpace() {
+ overprintMask = 0x0f;
}
GfxColorSpace::~GfxColorSpace() {
}
-GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
+GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) {
GfxColorSpace *cs;
Object obj1;
+ if (recursion > colorSpaceRecursionLimit) {
+ error(errSyntaxError, -1, "Loop detected in color space objects");
+ return NULL;
+ }
cs = NULL;
if (csObj->isName()) {
if (csObj->isName("DeviceGray") || csObj->isName("G")) {
@@ -107,9 +120,9 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
} else if (csObj->isName("Pattern")) {
cs = new GfxPatternColorSpace(NULL);
} else {
- error(-1, "Bad color space '%s'", csObj->getName());
+ error(errSyntaxError, -1, "Bad color space '{0:s}'", csObj->getName());
}
- } else if (csObj->isArray()) {
+ } else if (csObj->isArray() && csObj->arrayGetLength() > 0) {
csObj->arrayGet(0, &obj1);
if (obj1.isName("DeviceGray") || obj1.isName("G")) {
cs = new GfxDeviceGrayColorSpace();
@@ -118,27 +131,27 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
} else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
cs = new GfxDeviceCMYKColorSpace();
} else if (obj1.isName("CalGray")) {
- cs = GfxCalGrayColorSpace::parse(csObj->getArray());
+ cs = GfxCalGrayColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("CalRGB")) {
- cs = GfxCalRGBColorSpace::parse(csObj->getArray());
+ cs = GfxCalRGBColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("Lab")) {
- cs = GfxLabColorSpace::parse(csObj->getArray());
+ cs = GfxLabColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("ICCBased")) {
- cs = GfxICCBasedColorSpace::parse(csObj->getArray());
+ cs = GfxICCBasedColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("Indexed") || obj1.isName("I")) {
- cs = GfxIndexedColorSpace::parse(csObj->getArray());
+ cs = GfxIndexedColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("Separation")) {
- cs = GfxSeparationColorSpace::parse(csObj->getArray());
+ cs = GfxSeparationColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("DeviceN")) {
- cs = GfxDeviceNColorSpace::parse(csObj->getArray());
+ cs = GfxDeviceNColorSpace::parse(csObj->getArray(), recursion);
} else if (obj1.isName("Pattern")) {
- cs = GfxPatternColorSpace::parse(csObj->getArray());
+ cs = GfxPatternColorSpace::parse(csObj->getArray(), recursion);
} else {
- error(-1, "Bad color space");
+ error(errSyntaxError, -1, "Bad color space");
}
obj1.free();
} else {
- error(-1, "Bad color space - expected name or array");
+ error(errSyntaxError, -1, "Bad color space - expected name or array");
}
return cs;
}
@@ -157,7 +170,7 @@ int GfxColorSpace::getNumColorSpaceModes() {
return nGfxColorSpaceModes;
}
-char *GfxColorSpace::getColorSpaceModeName(int idx) {
+const char *GfxColorSpace::getColorSpaceModeName(int idx) {
return gfxColorSpaceModeNames[idx];
}
@@ -188,6 +201,7 @@ void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = clip01(gfxColorComp1 - color->c[0]);
}
+
void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
}
@@ -219,13 +233,17 @@ GfxColorSpace *GfxCalGrayColorSpace::copy() {
return cs;
}
-GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, int recursion) {
GfxCalGrayColorSpace *cs;
Object obj1, obj2, obj3;
+ if (arr->getLength() < 2) {
+ error(errSyntaxError, -1, "Bad CalGray color space");
+ return NULL;
+ }
arr->get(1, &obj1);
if (!obj1.isDict()) {
- error(-1, "Bad CalGray color space");
+ error(errSyntaxError, -1, "Bad CalGray color space");
obj1.free();
return NULL;
}
@@ -277,6 +295,7 @@ void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = clip01(gfxColorComp1 - color->c[0]);
}
+
void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
}
@@ -326,6 +345,7 @@ void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+
void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
color->c[1] = 0;
@@ -368,14 +388,18 @@ GfxColorSpace *GfxCalRGBColorSpace::copy() {
return cs;
}
-GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, int recursion) {
GfxCalRGBColorSpace *cs;
Object obj1, obj2, obj3;
int i;
+ if (arr->getLength() < 2) {
+ error(errSyntaxError, -1, "Bad CalRGB color space");
+ return NULL;
+ }
arr->get(1, &obj1);
if (!obj1.isDict()) {
- error(-1, "Bad CalRGB color space");
+ error(errSyntaxError, -1, "Bad CalRGB color space");
obj1.free();
return NULL;
}
@@ -463,6 +487,7 @@ void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+
void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
color->c[1] = 0;
@@ -559,6 +584,7 @@ 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;
@@ -608,13 +634,17 @@ GfxColorSpace *GfxLabColorSpace::copy() {
return cs;
}
-GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxLabColorSpace::parse(Array *arr, int recursion) {
GfxLabColorSpace *cs;
Object obj1, obj2, obj3;
+ if (arr->getLength() < 2) {
+ error(errSyntaxError, -1, "Bad Lab color space");
+ return NULL;
+ }
arr->get(1, &obj1);
if (!obj1.isDict()) {
- error(-1, "Bad Lab color space");
+ error(errSyntaxError, -1, "Bad Lab color space");
obj1.free();
return NULL;
}
@@ -743,6 +773,7 @@ void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+
void GfxLabColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
if (aMin > 0) {
@@ -800,7 +831,7 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() {
return cs;
}
-GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, int recursion) {
GfxICCBasedColorSpace *cs;
Ref iccProfileStreamA;
int nCompsA;
@@ -809,6 +840,10 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
Object obj1, obj2, obj3;
int i;
+ if (arr->getLength() < 2) {
+ error(errSyntaxError, -1, "Bad ICCBased color space");
+ return NULL;
+ }
arr->getNF(1, &obj1);
if (obj1.isRef()) {
iccProfileStreamA = obj1.getRef();
@@ -819,26 +854,27 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
obj1.free();
arr->get(1, &obj1);
if (!obj1.isStream()) {
- error(-1, "Bad ICCBased color space (stream)");
+ error(errSyntaxError, -1, "Bad ICCBased color space (stream)");
obj1.free();
return NULL;
}
dict = obj1.streamGetDict();
if (!dict->lookup("N", &obj2)->isInt()) {
- error(-1, "Bad ICCBased color space (N)");
+ error(errSyntaxError, -1, "Bad ICCBased color space (N)");
obj2.free();
obj1.free();
return NULL;
}
nCompsA = obj2.getInt();
obj2.free();
- if (nCompsA > gfxColorMaxComps) {
- error(-1, "ICCBased color space with too many (%d > %d) components",
- nCompsA, gfxColorMaxComps);
- nCompsA = gfxColorMaxComps;
+ if (nCompsA > 4) {
+ error(errSyntaxError, -1,
+ "ICCBased color space with too many ({0:d} > 4) components",
+ nCompsA);
+ nCompsA = 4;
}
if (dict->lookup("Alternate", &obj2)->isNull() ||
- !(altA = GfxColorSpace::parse(&obj2))) {
+ !(altA = GfxColorSpace::parse(&obj2, recursion + 1))) {
switch (nCompsA) {
case 1:
altA = new GfxDeviceGrayColorSpace();
@@ -850,7 +886,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
altA = new GfxDeviceCMYKColorSpace();
break;
default:
- error(-1, "Bad ICCBased color space - invalid N");
+ error(errSyntaxError, -1, "Bad ICCBased color space - invalid N");
obj2.free();
obj1.free();
return NULL;
@@ -886,6 +922,7 @@ void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(color, cmyk);
}
+
void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) {
int i;
@@ -927,6 +964,7 @@ GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
indexHigh = indexHighA;
lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(),
sizeof(Guchar));
+ overprintMask = base->getOverprintMask();
}
GfxIndexedColorSpace::~GfxIndexedColorSpace() {
@@ -943,7 +981,7 @@ GfxColorSpace *GfxIndexedColorSpace::copy() {
return cs;
}
-GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, int recursion) {
GfxIndexedColorSpace *cs;
GfxColorSpace *baseA;
int indexHighA;
@@ -953,17 +991,17 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
int n, i, j;
if (arr->getLength() != 4) {
- error(-1, "Bad Indexed color space");
+ error(errSyntaxError, -1, "Bad Indexed color space");
goto err1;
}
arr->get(1, &obj1);
- if (!(baseA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Indexed color space (base color space)");
+ if (!(baseA = GfxColorSpace::parse(&obj1, recursion + 1))) {
+ error(errSyntaxError, -1, "Bad Indexed color space (base color space)");
goto err2;
}
obj1.free();
if (!arr->get(2, &obj1)->isInt()) {
- error(-1, "Bad Indexed color space (hival)");
+ error(errSyntaxError, -1, "Bad Indexed color space (hival)");
delete baseA;
goto err2;
}
@@ -973,7 +1011,8 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
// values larger than 255 creates a security hole: if nComps *
// indexHigh is greater than 2^31, the loop below may overwrite
// past the end of the array
- error(-1, "Bad Indexed color space (invalid indexHigh value)");
+ error(errSyntaxError, -1,
+ "Bad Indexed color space (invalid indexHigh value)");
delete baseA;
goto err2;
}
@@ -986,8 +1025,9 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
for (i = 0; i <= indexHighA; ++i) {
for (j = 0; j < n; ++j) {
if ((x = obj1.streamGetChar()) == EOF) {
- error(-1, "Bad Indexed color space (lookup table stream too short)");
- goto err3;
+ error(errSyntaxError, -1,
+ "Bad Indexed color space (lookup table stream too short)");
+ cs->indexHigh = indexHighA = i - 1;
}
cs->lookup[i*n + j] = (Guchar)x;
}
@@ -995,8 +1035,9 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
obj1.streamClose();
} else if (obj1.isString()) {
if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
- error(-1, "Bad Indexed color space (lookup table string too short)");
- goto err3;
+ error(errSyntaxError, -1,
+ "Bad Indexed color space (lookup table string too short)");
+ cs->indexHigh = indexHighA = obj1.getString()->getLength() / n - 1;
}
s = obj1.getString()->getCString();
for (i = 0; i <= indexHighA; ++i) {
@@ -1005,7 +1046,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
}
}
} else {
- error(-1, "Bad Indexed color space (lookup table)");
+ error(errSyntaxError, -1, "Bad Indexed color space (lookup table)");
goto err3;
}
obj1.free();
@@ -1052,6 +1093,7 @@ void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
base->getCMYK(mapColorToBase(color, &color2), cmyk);
}
+
void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = 0;
}
@@ -1074,6 +1116,27 @@ GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
alt = altA;
func = funcA;
nonMarking = !name->cmp("None");
+ if (!name->cmp("Cyan")) {
+ overprintMask = 0x01;
+ } else if (!name->cmp("Magenta")) {
+ overprintMask = 0x02;
+ } else if (!name->cmp("Yellow")) {
+ overprintMask = 0x04;
+ } else if (!name->cmp("Black")) {
+ overprintMask = 0x08;
+ }
+}
+
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
+ GfxColorSpace *altA,
+ Function *funcA,
+ GBool nonMarkingA,
+ Guint overprintMaskA) {
+ name = nameA;
+ alt = altA;
+ func = funcA;
+ nonMarking = nonMarkingA;
+ overprintMask = overprintMaskA;
}
GfxSeparationColorSpace::~GfxSeparationColorSpace() {
@@ -1083,11 +1146,12 @@ GfxSeparationColorSpace::~GfxSeparationColorSpace() {
}
GfxColorSpace *GfxSeparationColorSpace::copy() {
- return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
+ return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(),
+ nonMarking, overprintMask);
}
//~ handle the 'All' and 'None' colorants
-GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, int recursion) {
GfxSeparationColorSpace *cs;
GString *nameA;
GfxColorSpace *altA;
@@ -1095,18 +1159,19 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
Object obj1;
if (arr->getLength() != 4) {
- error(-1, "Bad Separation color space");
+ error(errSyntaxError, -1, "Bad Separation color space");
goto err1;
}
if (!arr->get(1, &obj1)->isName()) {
- error(-1, "Bad Separation color space (name)");
+ error(errSyntaxError, -1, "Bad Separation color space (name)");
goto err2;
}
nameA = new GString(obj1.getName());
obj1.free();
arr->get(2, &obj1);
- if (!(altA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Separation color space (alternate color space)");
+ if (!(altA = GfxColorSpace::parse(&obj1, recursion + 1))) {
+ error(errSyntaxError, -1,
+ "Bad Separation color space (alternate color space)");
goto err3;
}
obj1.free();
@@ -1170,6 +1235,7 @@ void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(&color2, cmyk);
}
+
void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) {
color->c[0] = gfxColorComp1;
}
@@ -1179,12 +1245,51 @@ void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) {
//------------------------------------------------------------------------
GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
+ GString **namesA,
GfxColorSpace *altA,
Function *funcA) {
+ int i;
+
+ nComps = nCompsA;
+ alt = altA;
+ func = funcA;
+ nonMarking = gTrue;
+ overprintMask = 0;
+ for (i = 0; i < nComps; ++i) {
+ names[i] = namesA[i];
+ if (names[i]->cmp("None")) {
+ nonMarking = gFalse;
+ }
+ if (!names[i]->cmp("Cyan")) {
+ overprintMask |= 0x01;
+ } else if (!names[i]->cmp("Magenta")) {
+ overprintMask |= 0x02;
+ } else if (!names[i]->cmp("Yellow")) {
+ overprintMask |= 0x04;
+ } else if (!names[i]->cmp("Black")) {
+ overprintMask |= 0x08;
+ } else {
+ overprintMask = 0x0f;
+ }
+ }
+}
+
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
+ GString **namesA,
+ GfxColorSpace *altA,
+ Function *funcA,
+ GBool nonMarkingA,
+ Guint overprintMaskA) {
+ int i;
+
nComps = nCompsA;
alt = altA;
func = funcA;
- nonMarking = gFalse;
+ nonMarking = nonMarkingA;
+ overprintMask = overprintMaskA;
+ for (i = 0; i < nComps; ++i) {
+ names[i] = namesA[i]->copy();
+ }
}
GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
@@ -1198,19 +1303,12 @@ GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
}
GfxColorSpace *GfxDeviceNColorSpace::copy() {
- GfxDeviceNColorSpace *cs;
- int i;
-
- cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
- for (i = 0; i < nComps; ++i) {
- cs->names[i] = names[i]->copy();
- }
- cs->nonMarking = nonMarking;
- return cs;
+ return new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(),
+ nonMarking, overprintMask);
}
//~ handle the 'None' colorant
-GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, int recursion) {
GfxDeviceNColorSpace *cs;
int nCompsA;
GString *namesA[gfxColorMaxComps];
@@ -1220,22 +1318,23 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
int i;
if (arr->getLength() != 4 && arr->getLength() != 5) {
- error(-1, "Bad DeviceN color space");
+ error(errSyntaxError, -1, "Bad DeviceN color space");
goto err1;
}
if (!arr->get(1, &obj1)->isArray()) {
- error(-1, "Bad DeviceN color space (names)");
+ error(errSyntaxError, -1, "Bad DeviceN color space (names)");
goto err2;
}
nCompsA = obj1.arrayGetLength();
if (nCompsA > gfxColorMaxComps) {
- error(-1, "DeviceN color space with too many (%d > %d) components",
+ error(errSyntaxError, -1,
+ "DeviceN color space with too many ({0:d} > {1:d}) components",
nCompsA, gfxColorMaxComps);
nCompsA = gfxColorMaxComps;
}
for (i = 0; i < nCompsA; ++i) {
if (!obj1.arrayGet(i, &obj2)->isName()) {
- error(-1, "Bad DeviceN color space (names)");
+ error(errSyntaxError, -1, "Bad DeviceN color space (names)");
obj2.free();
goto err2;
}
@@ -1244,8 +1343,9 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
}
obj1.free();
arr->get(2, &obj1);
- if (!(altA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad DeviceN color space (alternate color space)");
+ if (!(altA = GfxColorSpace::parse(&obj1, recursion + 1))) {
+ error(errSyntaxError, -1,
+ "Bad DeviceN color space (alternate color space)");
goto err3;
}
obj1.free();
@@ -1254,14 +1354,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
goto err4;
}
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;
- }
- }
+ cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA);
return cs;
err4:
@@ -1321,6 +1414,7 @@ void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(&color2, cmyk);
}
+
void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) {
int i;
@@ -1348,20 +1442,21 @@ GfxColorSpace *GfxPatternColorSpace::copy() {
(GfxColorSpace *)NULL);
}
-GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, int recursion) {
GfxPatternColorSpace *cs;
GfxColorSpace *underA;
Object obj1;
if (arr->getLength() != 1 && arr->getLength() != 2) {
- error(-1, "Bad Pattern color space");
+ error(errSyntaxError, -1, "Bad Pattern color space");
return NULL;
}
underA = NULL;
if (arr->getLength() == 2) {
arr->get(1, &obj1);
- if (!(underA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Pattern color space (underlying color space)");
+ if (!(underA = GfxColorSpace::parse(&obj1, recursion + 1))) {
+ error(errSyntaxError, -1,
+ "Bad Pattern color space (underlying color space)");
obj1.free();
return NULL;
}
@@ -1384,6 +1479,7 @@ void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = 1;
}
+
void GfxPatternColorSpace::getDefaultColor(GfxColor *color) {
// not used
}
@@ -1443,14 +1539,14 @@ GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) {
paintTypeA = obj1.getInt();
} else {
paintTypeA = 1;
- error(-1, "Invalid or missing PaintType in pattern");
+ error(errSyntaxWarning, -1, "Invalid or missing PaintType in pattern");
}
obj1.free();
if (dict->lookup("TilingType", &obj1)->isInt()) {
tilingTypeA = obj1.getInt();
} else {
tilingTypeA = 1;
- error(-1, "Invalid or missing TilingType in pattern");
+ error(errSyntaxWarning, -1, "Invalid or missing TilingType in pattern");
}
obj1.free();
bboxA[0] = bboxA[1] = 0;
@@ -1464,27 +1560,27 @@ GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) {
obj2.free();
}
} else {
- error(-1, "Invalid or missing BBox in pattern");
+ error(errSyntaxError, -1, "Invalid or missing BBox in pattern");
}
obj1.free();
if (dict->lookup("XStep", &obj1)->isNum()) {
xStepA = obj1.getNum();
} else {
xStepA = 1;
- error(-1, "Invalid or missing XStep in pattern");
+ error(errSyntaxError, -1, "Invalid or missing XStep in pattern");
}
obj1.free();
if (dict->lookup("YStep", &obj1)->isNum()) {
yStepA = obj1.getNum();
} else {
yStepA = 1;
- error(-1, "Invalid or missing YStep in pattern");
+ error(errSyntaxError, -1, "Invalid or missing YStep in pattern");
}
obj1.free();
if (!dict->lookup("Resources", &resDictA)->isDict()) {
resDictA.free();
resDictA.initNull();
- error(-1, "Invalid or missing Resources in pattern");
+ error(errSyntaxError, -1, "Invalid or missing Resources in pattern");
}
matrixA[0] = 1; matrixA[1] = 0;
matrixA[2] = 0; matrixA[3] = 1;
@@ -1643,7 +1739,7 @@ GfxShading *GfxShading::parse(Object *obj) {
}
if (!dict->lookup("ShadingType", &obj1)->isInt()) {
- error(-1, "Invalid ShadingType in shading dictionary");
+ error(errSyntaxError, -1, "Invalid ShadingType in shading dictionary");
obj1.free();
return NULL;
}
@@ -1664,7 +1760,7 @@ GfxShading *GfxShading::parse(Object *obj) {
if (obj->isStream()) {
shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream());
} else {
- error(-1, "Invalid Type 4 shading object");
+ error(errSyntaxError, -1, "Invalid Type 4 shading object");
goto err1;
}
break;
@@ -1672,7 +1768,7 @@ GfxShading *GfxShading::parse(Object *obj) {
if (obj->isStream()) {
shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream());
} else {
- error(-1, "Invalid Type 5 shading object");
+ error(errSyntaxError, -1, "Invalid Type 5 shading object");
goto err1;
}
break;
@@ -1680,7 +1776,7 @@ GfxShading *GfxShading::parse(Object *obj) {
if (obj->isStream()) {
shading = GfxPatchMeshShading::parse(6, dict, obj->getStream());
} else {
- error(-1, "Invalid Type 6 shading object");
+ error(errSyntaxError, -1, "Invalid Type 6 shading object");
goto err1;
}
break;
@@ -1688,12 +1784,12 @@ GfxShading *GfxShading::parse(Object *obj) {
if (obj->isStream()) {
shading = GfxPatchMeshShading::parse(7, dict, obj->getStream());
} else {
- error(-1, "Invalid Type 7 shading object");
+ error(errSyntaxError, -1, "Invalid Type 7 shading object");
goto err1;
}
break;
default:
- error(-1, "Unimplemented shading type %d", typeA);
+ error(errSyntaxError, -1, "Unknown shading type {0:d}", typeA);
goto err1;
}
@@ -1709,7 +1805,7 @@ GBool GfxShading::init(Dict *dict) {
dict->lookup("ColorSpace", &obj1);
if (!(colorSpace = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad color space in shading dictionary");
+ error(errSyntaxError, -1, "Bad color space in shading dictionary");
obj1.free();
return gFalse;
}
@@ -1727,7 +1823,7 @@ GBool GfxShading::init(Dict *dict) {
obj2.free();
}
} else {
- error(-1, "Bad Background in shading dictionary");
+ error(errSyntaxError, -1, "Bad Background in shading dictionary");
}
}
obj1.free();
@@ -1746,7 +1842,7 @@ GBool GfxShading::init(Dict *dict) {
yMax = obj1.arrayGet(3, &obj2)->getNum();
obj2.free();
} else {
- error(-1, "Bad BBox in shading dictionary");
+ error(errSyntaxError, -1, "Bad BBox in shading dictionary");
}
}
obj1.free();
@@ -1853,7 +1949,8 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) {
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Invalid Function array in shading dictionary");
goto err1;
}
for (i = 0; i < nFuncsA; ++i) {
@@ -1946,7 +2043,7 @@ GfxAxialShading::GfxAxialShading(GfxAxialShading *shading):
x1 = shading->x1;
y1 = shading->y1;
t0 = shading->t0;
- y1 = shading->t1;
+ t1 = shading->t1;
nFuncs = shading->nFuncs;
for (i = 0; i < nFuncs; ++i) {
funcs[i] = shading->funcs[i]->copy();
@@ -1985,7 +2082,8 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
y1A = obj1.arrayGet(3, &obj2)->getNum();
obj2.free();
} else {
- error(-1, "Missing or invalid Coords in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid Coords in shading dictionary");
goto err1;
}
obj1.free();
@@ -2005,7 +2103,8 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Invalid Function array in shading dictionary");
goto err1;
}
for (i = 0; i < nFuncsA; ++i) {
@@ -2110,7 +2209,7 @@ GfxRadialShading::GfxRadialShading(GfxRadialShading *shading):
y1 = shading->y1;
r1 = shading->r1;
t0 = shading->t0;
- y1 = shading->t1;
+ t1 = shading->t1;
nFuncs = shading->nFuncs;
for (i = 0; i < nFuncs; ++i) {
funcs[i] = shading->funcs[i]->copy();
@@ -2153,7 +2252,8 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
r1A = obj1.arrayGet(5, &obj2)->getNum();
obj2.free();
} else {
- error(-1, "Missing or invalid Coords in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid Coords in shading dictionary");
goto err1;
}
obj1.free();
@@ -2173,7 +2273,8 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Invalid Function array in shading dictionary");
goto err1;
}
for (i = 0; i < nFuncsA; ++i) {
@@ -2378,14 +2479,16 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
coordBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerCoordinate in shading dictionary");
goto err2;
}
obj1.free();
if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
compBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerComponent in shading dictionary");
goto err2;
}
obj1.free();
@@ -2394,7 +2497,8 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
flagBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerFlag in shading dictionary");
goto err2;
}
obj1.free();
@@ -2402,7 +2506,8 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
if (dict->lookup("VerticesPerRow", &obj1)->isInt()) {
vertsPerRow = obj1.getInt();
} else {
- error(-1, "Missing or invalid VerticesPerRow in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid VerticesPerRow in shading dictionary");
goto err2;
}
obj1.free();
@@ -2428,7 +2533,8 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
}
nComps = i;
} else {
- error(-1, "Missing or invalid Decode array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid Decode array in shading dictionary");
goto err2;
}
obj1.free();
@@ -2437,7 +2543,8 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Invalid Function array in shading dictionary");
goto err1;
}
for (i = 0; i < nFuncsA; ++i) {
@@ -2678,7 +2785,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
double x[16], y[16];
Guint xi, yi;
GfxColorComp c[4][gfxColorMaxComps];
- Guint ci[4];
+ Guint ci;
GfxShadingBitBuf *bitBuf;
Object obj1, obj2;
int i, j;
@@ -2686,21 +2793,24 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
coordBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerCoordinate in shading dictionary");
goto err2;
}
obj1.free();
if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
compBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerComponent in shading dictionary");
goto err2;
}
obj1.free();
if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
flagBits = obj1.getInt();
} else {
- error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid BitsPerFlag in shading dictionary");
goto err2;
}
obj1.free();
@@ -2725,7 +2835,8 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
}
nComps = i;
} else {
- error(-1, "Missing or invalid Decode array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid Decode array in shading dictionary");
goto err2;
}
obj1.free();
@@ -2734,7 +2845,8 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
+ error(errSyntaxError, -1,
+ "Invalid Function array in shading dictionary");
goto err1;
}
for (i = 0; i < nFuncsA; ++i) {
@@ -2796,10 +2908,10 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
}
for (i = 0; i < nColors; ++i) {
for (j = 0; j < nComps; ++j) {
- if (!bitBuf->getBits(compBits, &ci[j])) {
+ if (!bitBuf->getBits(compBits, &ci)) {
break;
}
- c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]);
+ c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci);
}
if (j < nComps) {
break;
@@ -3187,7 +3299,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
GfxIndexedColorSpace *indexedCS;
GfxSeparationColorSpace *sepCS;
int maxPixel, indexHigh;
- Guchar *lookup2;
+ Guchar *indexedLookup;
Function *sepFunc;
Object obj;
double x[gfxColorMaxComps];
@@ -3204,6 +3316,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
// initialize
for (k = 0; k < gfxColorMaxComps; ++k) {
lookup[k] = NULL;
+ lookup2[k] = NULL;
}
// get decode map
@@ -3212,9 +3325,13 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
} else if (decode->isArray()) {
nComps = decode->arrayGetLength() / 2;
- if (nComps != colorSpace->getNComps()) {
+ if (nComps < colorSpace->getNComps()) {
goto err1;
}
+ if (nComps > colorSpace->getNComps()) {
+ error(errSyntaxWarning, -1, "Too many elements in Decode array");
+ nComps = colorSpace->getNComps();
+ }
for (i = 0; i < nComps; ++i) {
decode->arrayGet(2*i, &obj);
if (!obj.isNum()) {
@@ -3236,10 +3353,18 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
// Construct a lookup table -- this stores pre-computed decoded
// values for each component, i.e., the result of applying the
// decode mapping to each possible image pixel component value.
- //
+ for (k = 0; k < nComps; ++k) {
+ lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ sizeof(GfxColorComp));
+ for (i = 0; i <= maxPixel; ++i) {
+ lookup[k][i] = dblToCol(decodeLow[k] +
+ (i * decodeRange[k]) / maxPixel);
+ }
+ }
+
// Optimization: for Indexed and Separation color spaces (which have
- // only one component), we store color values in the lookup table
- // rather than component values.
+ // only one component), we pre-compute a second lookup table with
+ // color values
colorSpace2 = NULL;
nComps2 = 0;
if (colorSpace->getMode() == csIndexed) {
@@ -3250,20 +3375,22 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
colorSpace2 = indexedCS->getBase();
indexHigh = indexedCS->getIndexHigh();
nComps2 = colorSpace2->getNComps();
- lookup2 = indexedCS->getLookup();
+ indexedLookup = indexedCS->getLookup();
colorSpace2->getDefaultRanges(x, y, indexHigh);
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
- if (j < 0) {
- j = 0;
- } else if (j > indexHigh) {
- j = indexHigh;
- }
- lookup[k][i] =
- dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]);
+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ sizeof(GfxColorComp));
+ }
+ for (i = 0; i <= maxPixel; ++i) {
+ j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
+ if (j < 0) {
+ j = 0;
+ } else if (j > indexHigh) {
+ j = indexHigh;
+ }
+ for (k = 0; k < nComps2; ++k) {
+ lookup2[k][i] =
+ dblToCol(x[k] + (indexedLookup[j*nComps2 + k] / 255.0) * y[k]);
}
}
} else if (colorSpace->getMode() == csSeparation) {
@@ -3272,21 +3399,14 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
nComps2 = colorSpace2->getNComps();
sepFunc = sepCS->getFunc();
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
- sepFunc->transform(x, y);
- lookup[k][i] = dblToCol(y[k]);
- }
+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ sizeof(GfxColorComp));
}
- } else {
- for (k = 0; k < nComps; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- lookup[k][i] = dblToCol(decodeLow[k] +
- (i * decodeRange[k]) / maxPixel);
+ for (i = 0; i <= maxPixel; ++i) {
+ x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+ sepFunc->transform(x, y);
+ for (k = 0; k < nComps2; ++k) {
+ lookup2[k][i] = dblToCol(y[k]);
}
}
}
@@ -3309,24 +3429,24 @@ GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
colorSpace2 = NULL;
for (k = 0; k < gfxColorMaxComps; ++k) {
lookup[k] = NULL;
+ lookup2[k] = NULL;
}
n = 1 << bits;
+ for (k = 0; k < nComps; ++k) {
+ lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
+ memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
+ }
if (colorSpace->getMode() == csIndexed) {
colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
+ lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
+ memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
}
} else if (colorSpace->getMode() == csSeparation) {
colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
- }
- } else {
- for (k = 0; k < nComps; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
+ lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
+ memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
}
}
for (i = 0; i < nComps; ++i) {
@@ -3342,6 +3462,7 @@ GfxImageColorMap::~GfxImageColorMap() {
delete colorSpace;
for (i = 0; i < gfxColorMaxComps; ++i) {
gfree(lookup[i]);
+ gfree(lookup2[i]);
}
}
@@ -3351,7 +3472,7 @@ void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) {
if (colorSpace2) {
for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
+ color.c[i] = lookup2[i][x[0]];
}
colorSpace2->getGray(&color, gray);
} else {
@@ -3368,7 +3489,7 @@ void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
if (colorSpace2) {
for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
+ color.c[i] = lookup2[i][x[0]];
}
colorSpace2->getRGB(&color, rgb);
} else {
@@ -3385,7 +3506,7 @@ void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
if (colorSpace2) {
for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
+ color.c[i] = lookup2[i][x[0]];
}
colorSpace2->getCMYK(&color, cmyk);
} else {
@@ -3396,6 +3517,7 @@ void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
}
}
+
void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
int maxPixel, i;
@@ -3405,6 +3527,88 @@ void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
}
}
+void GfxImageColorMap::getGrayByteLine(Guchar *in, Guchar *out, int n) {
+ GfxColor color;
+ GfxGray gray;
+ int i, j;
+
+ if (colorSpace2) {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = lookup2[i][in[j]];
+ }
+ colorSpace2->getGray(&color, &gray);
+ out[j] = colToByte(gray);
+ }
+ } else {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[i][in[j * nComps + i]];
+ }
+ colorSpace->getGray(&color, &gray);
+ out[j] = colToByte(gray);
+ }
+ }
+}
+
+void GfxImageColorMap::getRGBByteLine(Guchar *in, Guchar *out, int n) {
+ GfxColor color;
+ GfxRGB rgb;
+ int i, j;
+
+ if (colorSpace2) {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = lookup2[i][in[j]];
+ }
+ colorSpace2->getRGB(&color, &rgb);
+ out[j*3] = colToByte(rgb.r);
+ out[j*3 + 1] = colToByte(rgb.g);
+ out[j*3 + 2] = colToByte(rgb.b);
+ }
+ } else {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[i][in[j * nComps + i]];
+ }
+ colorSpace->getRGB(&color, &rgb);
+ out[j*3] = colToByte(rgb.r);
+ out[j*3 + 1] = colToByte(rgb.g);
+ out[j*3 + 2] = colToByte(rgb.b);
+ }
+ }
+}
+
+void GfxImageColorMap::getCMYKByteLine(Guchar *in, Guchar *out, int n) {
+ GfxColor color;
+ GfxCMYK cmyk;
+ int i, j;
+
+ if (colorSpace2) {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = lookup2[i][in[j]];
+ }
+ colorSpace2->getCMYK(&color, &cmyk);
+ out[j*4] = colToByte(cmyk.c);
+ out[j*4 + 1] = colToByte(cmyk.m);
+ out[j*4 + 2] = colToByte(cmyk.y);
+ out[j*4 + 3] = colToByte(cmyk.k);
+ }
+ } else {
+ for (j = 0; j < n; ++j) {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[i][in[j * nComps + i]];
+ }
+ colorSpace->getCMYK(&color, &cmyk);
+ out[j*4] = colToByte(cmyk.c);
+ out[j*4 + 1] = colToByte(cmyk.m);
+ out[j*4 + 2] = colToByte(cmyk.y);
+ out[j*4 + 3] = colToByte(cmyk.k);
+ }
+ }
+}
+
//------------------------------------------------------------------------
// GfxSubpath and GfxPath
//------------------------------------------------------------------------
@@ -3442,7 +3646,7 @@ GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
void GfxSubpath::lineTo(double x1, double y1) {
if (n >= size) {
- size += 16;
+ size *= 2;
x = (double *)greallocn(x, size, sizeof(double));
y = (double *)greallocn(y, size, sizeof(double));
curve = (GBool *)greallocn(curve, size, sizeof(GBool));
@@ -3456,7 +3660,7 @@ void GfxSubpath::lineTo(double x1, double y1) {
void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
double x3, double y3) {
if (n+3 > size) {
- size += 16;
+ size *= 2;
x = (double *)greallocn(x, size, sizeof(double));
y = (double *)greallocn(y, size, sizeof(double));
curve = (GBool *)greallocn(curve, size, sizeof(GBool));
@@ -3526,13 +3730,18 @@ void GfxPath::moveTo(double x, double y) {
}
void GfxPath::lineTo(double x, double y) {
- if (justMoved) {
+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
if (n >= size) {
- size += 16;
+ size *= 2;
subpaths = (GfxSubpath **)
greallocn(subpaths, size, sizeof(GfxSubpath *));
}
- subpaths[n] = new GfxSubpath(firstX, firstY);
+ if (justMoved) {
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ } else {
+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
+ subpaths[n-1]->getLastY());
+ }
++n;
justMoved = gFalse;
}
@@ -3541,13 +3750,18 @@ void GfxPath::lineTo(double x, double y) {
void GfxPath::curveTo(double x1, double y1, double x2, double y2,
double x3, double y3) {
- if (justMoved) {
+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
if (n >= size) {
- size += 16;
+ size *= 2;
subpaths = (GfxSubpath **)
greallocn(subpaths, size, sizeof(GfxSubpath *));
}
- subpaths[n] = new GfxSubpath(firstX, firstY);
+ if (justMoved) {
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ } else {
+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
+ subpaths[n-1]->getLastY());
+ }
++n;
justMoved = gFalse;
}
@@ -3559,7 +3773,7 @@ void GfxPath::close() {
// moveto/closepath/clip, which defines an empty clipping region
if (justMoved) {
if (n >= size) {
- size += 16;
+ size *= 2;
subpaths = (GfxSubpath **)
greallocn(subpaths, size, sizeof(GfxSubpath *));
}
@@ -3658,6 +3872,7 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
strokeOpacity = 1;
fillOverprint = gFalse;
strokeOverprint = gFalse;
+ overprintMode = 0;
transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
lineWidth = 1;
@@ -3719,13 +3934,10 @@ GfxState::~GfxState() {
// this gets set to NULL by restore()
delete path;
}
- if (saved) {
- delete saved;
- }
}
// Used for copy();
-GfxState::GfxState(GfxState *state) {
+GfxState::GfxState(GfxState *state, GBool copyPath) {
int i;
memcpy(this, state, sizeof(GfxState));
@@ -3750,6 +3962,9 @@ GfxState::GfxState(GfxState *state) {
lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
}
+ if (copyPath) {
+ path = state->path->copy();
+ }
saved = NULL;
}
@@ -4056,6 +4271,60 @@ void GfxState::clipToStrokePath() {
}
}
+void GfxState::clipToRect(double xMin, double yMin, double xMax, double yMax) {
+ double x, y, xMin1, yMin1, xMax1, yMax1;
+
+ transform(xMin, yMin, &x, &y);
+ xMin1 = xMax1 = x;
+ yMin1 = yMax1 = y;
+ transform(xMax, yMin, &x, &y);
+ if (x < xMin1) {
+ xMin1 = x;
+ } else if (x > xMax1) {
+ xMax1 = x;
+ }
+ if (y < yMin1) {
+ yMin1 = y;
+ } else if (y > yMax1) {
+ yMax1 = y;
+ }
+ transform(xMax, yMax, &x, &y);
+ if (x < xMin1) {
+ xMin1 = x;
+ } else if (x > xMax1) {
+ xMax1 = x;
+ }
+ if (y < yMin1) {
+ yMin1 = y;
+ } else if (y > yMax1) {
+ yMax1 = y;
+ }
+ transform(xMin, yMax, &x, &y);
+ if (x < xMin1) {
+ xMin1 = x;
+ } else if (x > xMax1) {
+ xMax1 = x;
+ }
+ if (y < yMin1) {
+ yMin1 = y;
+ } else if (y > yMax1) {
+ yMax1 = y;
+ }
+
+ if (xMin1 > clipXMin) {
+ clipXMin = xMin1;
+ }
+ if (yMin1 > clipYMin) {
+ clipYMin = yMin1;
+ }
+ if (xMax1 < clipXMax) {
+ clipXMax = xMax1;
+ }
+ if (yMax1 < clipYMax) {
+ clipYMax = yMax1;
+ }
+}
+
void GfxState::textShift(double tx, double ty) {
double dx, dy;
diff --git a/xpdf/GfxState.h b/xpdf/GfxState.h
index f85643d..5d57de9 100644
--- a/xpdf/GfxState.h
+++ b/xpdf/GfxState.h
@@ -109,6 +109,8 @@ struct GfxCMYK {
GfxColorComp c, m, y, k;
};
+
+
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
@@ -138,7 +140,7 @@ public:
virtual GfxColorSpaceMode getMode() = 0;
// Construct a color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Object *csObj);
+ static GfxColorSpace *parse(Object *csObj, int recursion = 0);
// Convert to gray, RGB, or CMYK.
virtual void getGray(GfxColor *color, GfxGray *gray) = 0;
@@ -160,13 +162,18 @@ public:
// mark the page (e.g., the "None" colorant).
virtual GBool isNonMarking() { return gFalse; }
+ // Return the color space's overprint mask.
+ Guint getOverprintMask() { return overprintMask; }
+
// Return the number of color space modes
static int getNumColorSpaceModes();
// Return the name of the <idx>th color space mode.
- static char *getColorSpaceModeName(int idx);
+ static const char *getColorSpaceModeName(int idx);
-private:
+protected:
+
+ Guint overprintMask;
};
//------------------------------------------------------------------------
@@ -204,7 +211,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csCalGray; }
// Construct a CalGray color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -264,7 +271,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csCalRGB; }
// Construct a CalRGB color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -328,7 +335,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csLab; }
// Construct a Lab color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -374,7 +381,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csICCBased; }
// Construct an ICCBased color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -410,8 +417,8 @@ public:
virtual GfxColorSpace *copy();
virtual GfxColorSpaceMode getMode() { return csIndexed; }
- // Construct a Lab color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ // Construct an Indexed color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -450,7 +457,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csSeparation; }
// Construct a Separation color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -468,6 +475,10 @@ public:
private:
+ GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
+ Function *funcA, GBool nonMarkingA,
+ Guint overprintMaskA);
+
GString *name; // colorant name
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
@@ -481,13 +492,14 @@ private:
class GfxDeviceNColorSpace: public GfxColorSpace {
public:
- GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func);
+ GfxDeviceNColorSpace(int nCompsA, GString **namesA,
+ GfxColorSpace *alt, Function *func);
virtual ~GfxDeviceNColorSpace();
virtual GfxColorSpace *copy();
virtual GfxColorSpaceMode getMode() { return csDeviceN; }
// Construct a DeviceN color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -505,6 +517,10 @@ public:
private:
+ GfxDeviceNColorSpace(int nCompsA, GString **namesA,
+ GfxColorSpace *alt, Function *func,
+ GBool nonMarkingA, Guint overprintMaskA);
+
int nComps; // number of components
GString // colorant names
*names[gfxColorMaxComps];
@@ -526,7 +542,7 @@ public:
virtual GfxColorSpaceMode getMode() { return csPattern; }
// Construct a Pattern color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
+ static GfxColorSpace *parse(Array *arr, int recursion);
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
@@ -878,6 +894,11 @@ public:
void getCMYK(Guchar *x, GfxCMYK *cmyk);
void getColor(Guchar *x, GfxColor *color);
+ // Convert a line of <n> pixels to 8-bit colors.
+ void getGrayByteLine(Guchar *in, Guchar *out, int n);
+ void getRGBByteLine(Guchar *in, Guchar *out, int n);
+ void getCMYKByteLine(Guchar *in, Guchar *out, int n);
+
private:
GfxImageColorMap(GfxImageColorMap *colorMap);
@@ -889,6 +910,8 @@ private:
int nComps2; // number of components in colorSpace2
GfxColorComp * // lookup table
lookup[gfxColorMaxComps];
+ GfxColorComp * // optimized case lookup table
+ lookup2[gfxColorMaxComps];
double // minimum values for each component
decodeLow[gfxColorMaxComps];
double // max - min value for each component
@@ -1023,7 +1046,8 @@ public:
~GfxState();
// Copy.
- GfxState *copy() { return new GfxState(this); }
+ GfxState *copy(GBool copyPath = gFalse)
+ { return new GfxState(this, copyPath); }
// Accessors.
double getHDPI() { return hDPI; }
@@ -1059,6 +1083,7 @@ public:
double getStrokeOpacity() { return strokeOpacity; }
GBool getFillOverprint() { return fillOverprint; }
GBool getStrokeOverprint() { return strokeOverprint; }
+ int getOverprintMode() { return overprintMode; }
Function **getTransfer() { return transfer; }
double getLineWidth() { return lineWidth; }
void getLineDash(double **dash, int *length, double *start)
@@ -1127,6 +1152,7 @@ public:
void setStrokeOpacity(double opac) { strokeOpacity = opac; }
void setFillOverprint(GBool op) { fillOverprint = op; }
void setStrokeOverprint(GBool op) { strokeOverprint = op; }
+ void setOverprintMode(int opm) { overprintMode = opm; }
void setTransfer(Function **funcs);
void setLineWidth(double width) { lineWidth = width; }
void setLineDash(double *dash, int length, double start);
@@ -1169,6 +1195,7 @@ public:
// Update clip region.
void clip();
void clipToStrokePath();
+ void clipToRect(double xMin, double yMin, double xMax, double yMax);
// Text position.
void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
@@ -1204,6 +1231,7 @@ private:
double strokeOpacity; // stroke opacity
GBool fillOverprint; // fill overprint
GBool strokeOverprint; // stroke overprint
+ int overprintMode; // overprint mode ("OPM")
Function *transfer[4]; // transfer function (entries may be: all
// NULL = identity; last three NULL =
// single function; all four non-NULL =
@@ -1238,7 +1266,7 @@ private:
GfxState *saved; // next GfxState on stack
- GfxState(GfxState *state);
+ GfxState(GfxState *state, GBool copyPath);
};
#endif
diff --git a/xpdf/GlobalParams.cc b/xpdf/GlobalParams.cc
index e2f2f90..63e932b 100644
--- a/xpdf/GlobalParams.cc
+++ b/xpdf/GlobalParams.cc
@@ -81,9 +81,9 @@ extern XpdfPluginVecTable xpdfPluginVecTable;
//------------------------------------------------------------------------
static struct {
- char *name;
- char *t1FileName;
- char *ttFileName;
+ const char *name;
+ const char *t1FileName;
+ const char *ttFileName;
} displayFontTab[] = {
{"Courier", "n022003l.pfb", "cour.ttf"},
{"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
@@ -103,13 +103,13 @@ static struct {
};
#ifdef WIN32
-static char *displayFontDirs[] = {
+static const char *displayFontDirs[] = {
"c:/windows/fonts",
"c:/winnt/fonts",
NULL
};
#else
-static char *displayFontDirs[] = {
+static const char *displayFontDirs[] = {
"/usr/share/ghostscript/fonts",
"/usr/local/share/ghostscript/fonts",
"/usr/share/fonts/default/Type1",
@@ -124,215 +124,138 @@ static char *displayFontDirs[] = {
GlobalParams *globalParams = NULL;
//------------------------------------------------------------------------
-// DisplayFontParam
+// PSFontParam16
//------------------------------------------------------------------------
-DisplayFontParam::DisplayFontParam(GString *nameA,
- DisplayFontParamKind kindA) {
+PSFontParam16::PSFontParam16(GString *nameA, int wModeA,
+ GString *psFontNameA, GString *encodingA) {
name = nameA;
- kind = kindA;
- switch (kind) {
- case displayFontT1:
- t1.fileName = NULL;
- break;
- case displayFontTT:
- tt.fileName = NULL;
- break;
- }
+ wMode = wModeA;
+ psFontName = psFontNameA;
+ encoding = encodingA;
}
-DisplayFontParam::~DisplayFontParam() {
+PSFontParam16::~PSFontParam16() {
delete name;
- switch (kind) {
- case displayFontT1:
- if (t1.fileName) {
- delete t1.fileName;
- }
- break;
- case displayFontTT:
- if (tt.fileName) {
- delete tt.fileName;
- }
- break;
- }
+ delete psFontName;
+ delete encoding;
}
-#ifdef WIN32
-
//------------------------------------------------------------------------
-// WinFontInfo
+// SysFontInfo
//------------------------------------------------------------------------
-class WinFontInfo: public DisplayFontParam {
+class SysFontInfo {
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);
+ GString *name;
+ GBool bold;
+ GBool italic;
+ GString *path;
+ SysFontType type;
+ int fontNum; // for TrueType collections
+
+ SysFontInfo(GString *nameA, GBool boldA, GBool italicA,
+ GString *pathA, SysFontType typeA, int fontNumA);
+ ~SysFontInfo();
+ GBool match(SysFontInfo *fi);
+ GBool match(GString *nameA, GBool boldA, GBool italicA);
};
-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)
-{
+SysFontInfo::SysFontInfo(GString *nameA, GBool boldA, GBool italicA,
+ GString *pathA, SysFontType typeA, int fontNumA) {
+ name = nameA;
bold = boldA;
italic = italicA;
- tt.fileName = fileNameA;
+ path = pathA;
+ type = typeA;
+ fontNum = fontNumA;
}
-WinFontInfo::~WinFontInfo() {
+SysFontInfo::~SysFontInfo() {
+ delete name;
+ delete path;
}
-GBool WinFontInfo::equals(WinFontInfo *fi) {
- return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic;
+GBool SysFontInfo::match(SysFontInfo *fi) {
+ return !strcasecmp(name->getCString(), fi->name->getCString()) &&
+ bold == fi->bold && italic == fi->italic;
+}
+
+GBool SysFontInfo::match(GString *nameA, GBool boldA, GBool italicA) {
+ return !strcasecmp(name->getCString(), nameA->getCString()) &&
+ bold == boldA && italic == italicA;
}
//------------------------------------------------------------------------
-// WinFontList
+// SysFontList
//------------------------------------------------------------------------
-class WinFontList {
+class SysFontList {
public:
- WinFontList(char *winFontDirA);
- ~WinFontList();
- WinFontInfo *find(GString *font);
+ SysFontList();
+ ~SysFontList();
+ SysFontInfo *find(GString *name);
+
+#ifdef WIN32
+ void scanWindowsFonts(char *winFontDir);
+#endif
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)
-};
+#ifdef WIN32
+ SysFontInfo *makeWindowsFont(char *name, int fontNum,
+ char *path);
+#endif
-WinFontList::WinFontList(char *winFontDirA) {
- OSVERSIONINFO version;
- char *path;
+ GList *fonts; // [SysFontInfo]
+};
+SysFontList::SysFontList() {
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);
+SysFontList::~SysFontList() {
+ deleteGList(fonts, SysFontInfo);
}
-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;
+SysFontInfo *SysFontList::find(GString *name) {
+ GString *name2;
GBool bold, italic;
- WinFontInfo *fi;
+ SysFontInfo *fi;
char c;
int n, i;
- name = font->copy();
+ name2 = name->copy();
// remove space, comma, dash chars
i = 0;
- while (i < name->getLength()) {
- c = name->getChar(i);
+ while (i < name2->getLength()) {
+ c = name2->getChar(i);
if (c == ' ' || c == ',' || c == '-') {
- name->del(i);
+ name2->del(i);
} else {
++i;
}
}
- n = name->getLength();
+ n = name2->getLength();
// remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.)
- if (!strcmp(name->getCString() + n - 2, "MT")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) {
+ name2->del(n - 2, 2);
n -= 2;
}
+ // look for "Regular"
+ if (n > 7 && !strcmp(name2->getCString() + n - 7, "Regular")) {
+ name2->del(n - 7, 7);
+ n -= 7;
+ }
+
// look for "Italic"
- if (!strcmp(name->getCString() + n - 6, "Italic")) {
- name->del(n - 6, 6);
+ if (n > 6 && !strcmp(name2->getCString() + n - 6, "Italic")) {
+ name2->del(n - 6, 6);
italic = gTrue;
n -= 6;
} else {
@@ -340,8 +263,8 @@ WinFontInfo *WinFontList::find(GString *font) {
}
// look for "Bold"
- if (!strcmp(name->getCString() + n - 4, "Bold")) {
- name->del(n - 4, 4);
+ if (n > 4 && !strcmp(name2->getCString() + n - 4, "Bold")) {
+ name2->del(n - 4, 4);
bold = gTrue;
n -= 4;
} else {
@@ -349,84 +272,183 @@ WinFontInfo *WinFontList::find(GString *font) {
}
// remove trailing "MT" (FooMT-Bold, etc.)
- if (!strcmp(name->getCString() + n - 2, "MT")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) {
+ name2->del(n - 2, 2);
n -= 2;
}
// remove trailing "PS"
- if (!strcmp(name->getCString() + n - 2, "PS")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "PS")) {
+ name2->del(n - 2, 2);
n -= 2;
}
+ // remove trailing "IdentityH"
+ if (n > 9 && !strcmp(name2->getCString() + n - 9, "IdentityH")) {
+ name2->del(n - 9, 9);
+ n -= 9;
+ }
+
// 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) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, bold, italic)) {
break;
}
fi = NULL;
}
+ if (!fi && bold) {
+ // try ignoring the bold flag
+ for (i = 0; i < fonts->getLength(); ++i) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, gFalse, italic)) {
+ break;
+ }
+ fi = NULL;
+ }
+ }
+ if (!fi && (bold || italic)) {
+ // try ignoring the bold and italic flags
+ for (i = 0; i < fonts->getLength(); ++i) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, gFalse, gFalse)) {
+ break;
+ }
+ fi = NULL;
+ }
+ }
- delete name;
+ delete name2;
return fi;
}
-int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data) {
- WinFontList *fl = (WinFontList *)data;
+#ifdef WIN32
+void SysFontList::scanWindowsFonts(char *winFontDir) {
+ OSVERSIONINFO version;
+ char *path;
+ DWORD idx, valNameLen, dataLen, type;
+ HKEY regKey;
+ char valName[1024], data[1024];
+ int n, fontNum;
+ char *p0, *p1;
+ GString *fontPath;
- EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl);
- return 1;
+ 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) {
+ idx = 0;
+ while (1) {
+ valNameLen = sizeof(valName) - 1;
+ dataLen = sizeof(data) - 1;
+ if (RegEnumValue(regKey, idx, valName, &valNameLen, NULL,
+ &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) {
+ break;
+ }
+ if (type == REG_SZ &&
+ valNameLen > 0 && valNameLen < sizeof(valName) &&
+ dataLen > 0 && dataLen < sizeof(data)) {
+ valName[valNameLen] = '\0';
+ data[dataLen] = '\0';
+ n = strlen(data);
+ if (!strcasecmp(data + n - 4, ".ttf") ||
+ !strcasecmp(data + n - 4, ".ttc")) {
+ fontPath = new GString(data);
+ if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) {
+ fontPath->insert(0, '\\');
+ fontPath->insert(0, winFontDir);
+ }
+ p0 = valName;
+ fontNum = 0;
+ while (*p0) {
+ p1 = strstr(p0, " & ");
+ if (p1) {
+ *p1 = '\0';
+ p1 = p1 + 3;
+ } else {
+ p1 = p0 + strlen(p0);
+ }
+ fonts->append(makeWindowsFont(p0, fontNum,
+ fontPath->getCString()));
+ p0 = p1;
+ ++fontNum;
+ }
+ delete fontPath;
+ }
+ }
+ ++idx;
+ }
+ RegCloseKey(regKey);
+ }
}
-int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data) {
- WinFontList *fl = (WinFontList *)data;
- WinFontInfo *fi;
+SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
+ char *path) {
+ int n;
+ GBool bold, italic;
+ GString *s;
+ char c;
+ int i;
+ SysFontType type;
- 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);
- }
+ n = strlen(name);
+ bold = italic = gFalse;
+
+ // remove trailing ' (TrueType)'
+ if (n > 11 && !strncmp(name + n - 11, " (TrueType)", 11)) {
+ n -= 11;
}
- return 1;
-}
-#endif // WIN32
+ // remove trailing ' Italic'
+ if (n > 7 && !strncmp(name + n - 7, " Italic", 7)) {
+ n -= 7;
+ italic = gTrue;
+ }
-//------------------------------------------------------------------------
-// PSFontParam
-//------------------------------------------------------------------------
+ // remove trailing ' Bold'
+ if (n > 5 && !strncmp(name + n - 5, " Bold", 5)) {
+ n -= 5;
+ bold = gTrue;
+ }
-PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
- GString *psFontNameA, GString *encodingA) {
- pdfFontName = pdfFontNameA;
- wMode = wModeA;
- psFontName = psFontNameA;
- encoding = encodingA;
-}
+ // remove trailing ' Regular'
+ if (n > 5 && !strncmp(name + n - 8, " Regular", 8)) {
+ n -= 8;
+ }
-PSFontParam::~PSFontParam() {
- delete pdfFontName;
- delete psFontName;
- if (encoding) {
- delete encoding;
+ //----- normalize the font name
+ s = new GString(name, n);
+ i = 0;
+ while (i < s->getLength()) {
+ c = s->getChar(i);
+ if (c == ' ' || c == ',' || c == '-') {
+ s->del(i);
+ } else {
+ ++i;
+ }
}
+
+ if (!strcasecmp(path + strlen(path) - 4, ".ttc")) {
+ type = sysFontTTC;
+ } else {
+ type = sysFontTTF;
+ }
+ return new SysFontInfo(s, bold, italic, new GString(path), type, fontNum);
}
+#endif
//------------------------------------------------------------------------
// KeyBinding
//------------------------------------------------------------------------
-KeyBinding::KeyBinding(int codeA, int modsA, int contextA, char *cmd0) {
+KeyBinding::KeyBinding(int codeA, int modsA, int contextA, const char *cmd0) {
code = codeA;
mods = modsA;
context = contextA;
@@ -435,7 +457,7 @@ KeyBinding::KeyBinding(int codeA, int modsA, int contextA, char *cmd0) {
}
KeyBinding::KeyBinding(int codeA, int modsA, int contextA,
- char *cmd0, char *cmd1) {
+ const char *cmd0, const char *cmd1) {
code = codeA;
mods = modsA;
context = contextA;
@@ -496,33 +518,32 @@ Plugin *Plugin::load(char *type, char *name) {
#ifdef WIN32
path->append(".dll");
if (!(libA = LoadLibrary(path->getCString()))) {
- error(-1, "Failed to load plugin '%s'",
- path->getCString());
+ error(errIO, -1, "Failed to load plugin '{0:t}'", path);
goto err1;
}
if (!(vt = (XpdfPluginVecTable *)
GetProcAddress(libA, "xpdfPluginVecTable"))) {
- error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
- path->getCString());
+ error(errIO, -1, "Failed to find xpdfPluginVecTable in plugin '{0:t}'",
+ path);
goto err2;
}
#else
//~ need to deal with other extensions here
path->append(".so");
if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) {
- error(-1, "Failed to load plugin '%s': %s",
- path->getCString(), dlerror());
+ error(errIO, -1, "Failed to load plugin '{0:t}': {1:s}",
+ path, dlerror());
goto err1;
}
if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) {
- error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
- path->getCString());
+ error(errIO, -1, "Failed to find xpdfPluginVecTable in plugin '{0:t}'",
+ path);
goto err2;
}
#endif
if (vt->version != xpdfPluginVecTable.version) {
- error(-1, "Plugin '%s' is wrong version", path->getCString());
+ error(errIO, -1, "Plugin '{0:t}' is wrong version", path);
goto err2;
}
memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable));
@@ -530,21 +551,20 @@ Plugin *Plugin::load(char *type, char *name) {
#ifdef WIN32
if (!(xpdfInitPlugin = (XpdfBool (*)(void))
GetProcAddress(libA, "xpdfInitPlugin"))) {
- error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
- path->getCString());
+ error(errIO, -1, "Failed to find xpdfInitPlugin in plugin '{0:t}'",
+ path);
goto err2;
}
#else
if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) {
- error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
- path->getCString());
+ error(errIO, -1, "Failed to find xpdfInitPlugin in plugin '{0:t}'",
+ path);
goto err2;
}
#endif
if (!(*xpdfInitPlugin)()) {
- error(-1, "Initialization of plugin '%s' failed",
- path->getCString());
+ error(errIO, -1, "Initialization of plugin '{0:t}' failed", path);
goto err2;
}
@@ -637,9 +657,10 @@ GlobalParams::GlobalParams(char *cfgFileName) {
unicodeMaps = new GHash(gTrue);
cMapDirs = new GHash(gTrue);
toUnicodeDirs = new GList();
- displayFonts = new GHash();
- displayCIDFonts = new GHash();
- displayNamedCIDFonts = new GHash();
+ fontFiles = new GHash(gTrue);
+ fontDirs = new GList();
+ ccFontFiles = new GHash(gTrue);
+ sysFonts = new SysFontList();
#if HAVE_PAPER_H
char *paperName;
const struct paper *paperType;
@@ -649,7 +670,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
psPaperWidth = (int)paperpswidth(paperType);
psPaperHeight = (int)paperpsheight(paperType);
} else {
- error(-1, "No paper information available - using defaults");
+ error(errConfig, -1, "No paper information available - using defaults");
psPaperWidth = defPaperWidth;
psPaperHeight = defPaperHeight;
}
@@ -668,16 +689,21 @@ GlobalParams::GlobalParams(char *cfgFileName) {
psDuplex = gFalse;
psLevel = psLevel2;
psFile = NULL;
- psFonts = new GHash();
- psNamedFonts16 = new GList();
- psFonts16 = new GList();
+ psResidentFonts = new GHash(gTrue);
+ psResidentFonts16 = new GList();
+ psResidentFontsCC = new GList();
psEmbedType1 = gTrue;
psEmbedTrueType = gTrue;
psEmbedCIDPostScript = gTrue;
psEmbedCIDTrueType = gTrue;
+ psFontPassthrough = gFalse;
psPreload = gFalse;
psOPI = gFalse;
psASCIIHex = gFalse;
+ psUncompressPreloadedImages = gFalse;
+ psRasterResolution = 300;
+ psRasterMono = gFalse;
+ psAlwaysRasterize = gFalse;
textEncoding = new GString("Latin1");
#if defined(WIN32)
textEOL = eolDOS;
@@ -688,13 +714,14 @@ GlobalParams::GlobalParams(char *cfgFileName) {
#endif
textPageBreaks = gTrue;
textKeepTinyChars = gFalse;
- fontDirs = new GList();
initialZoom = new GString("125");
continuousView = gFalse;
enableT1lib = gTrue;
enableFreeType = gTrue;
+ disableFreeTypeHinting = gFalse;
antialias = gTrue;
vectorAntialias = gTrue;
+ antialiasPrinting = gFalse;
strokeAdjust = gTrue;
screenType = screenUnset;
screenSize = -1;
@@ -702,6 +729,10 @@ GlobalParams::GlobalParams(char *cfgFileName) {
screenGamma = 1.0;
screenBlackThreshold = 0.0;
screenWhiteThreshold = 1.0;
+ minLineWidth = 0.0;
+ drawAnnotations = gTrue;
+ overprintPreview = gFalse;
+ launchCommand = NULL;
urlCommand = NULL;
movieCommand = NULL;
mapNumericCharNames = gTrue;
@@ -716,10 +747,6 @@ GlobalParams::GlobalParams(char *cfgFileName) {
unicodeMapCache = new UnicodeMapCache();
cMapCache = new CMapCache();
-#ifdef WIN32
- winFontList = NULL;
-#endif
-
#ifdef ENABLE_PLUGINS
plugins = new GList();
securityHandlers = new GList();
@@ -764,7 +791,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
}
}
if (!f) {
-#if defined(WIN32) && !defined(__CYGWIN32__)
+#ifdef WIN32
char buf[512];
i = GetModuleFileName(NULL, buf, sizeof(buf));
if (i <= 0 || i >= sizeof(buf)) {
@@ -941,7 +968,7 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
} else {
for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
}
- tokens->append(new GString(p1, p2 - p1));
+ tokens->append(new GString(p1, (int)(p2 - p1)));
p1 = *p2 ? p2 + 1 : p2;
}
@@ -952,16 +979,17 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
if (!cmd->cmp("include")) {
if (tokens->getLength() == 2) {
incFile = (GString *)tokens->get(1);
- if ((f2 = fopen(incFile->getCString(), "r"))) {
+ if ((f2 = openFile(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);
+ error(errConfig, -1,
+ "Couldn't find included config file: '{0:t}' ({1:t}:{2:d})",
+ incFile, fileName, line);
}
} else {
- error(-1, "Bad 'include' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'include' config file command ({0:t}:{1:d})",
+ fileName, line);
}
} else if (!cmd->cmp("nameToUnicode")) {
parseNameToUnicode(tokens, fileName, line);
@@ -975,31 +1003,14 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
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("fontFile")) {
+ parseFontFile(tokens, fileName, line);
+ } else if (!cmd->cmp("fontDir")) {
+ parseFontDir(tokens, fileName, line);
+ } else if (!cmd->cmp("fontFileCC")) {
+ parseFontFileCC(tokens, 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")) {
@@ -1017,6 +1028,12 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
} else if (!cmd->cmp("psLevel")) {
parsePSLevel(tokens, fileName, line);
+ } else if (!cmd->cmp("psResidentFont")) {
+ parsePSResidentFont(tokens, fileName, line);
+ } else if (!cmd->cmp("psResidentFont16")) {
+ parsePSResidentFont16(tokens, fileName, line);
+ } else if (!cmd->cmp("psResidentFontCC")) {
+ parsePSResidentFontCC(tokens, fileName, line);
} else if (!cmd->cmp("psEmbedType1Fonts")) {
parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
} else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
@@ -1028,12 +1045,26 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
} else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
tokens, fileName, line);
+ } else if (!cmd->cmp("psFontPassthrough")) {
+ parseYesNo("psFontPassthrough", &psFontPassthrough,
+ 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("psUncompressPreloadedImages")) {
+ parseYesNo("psUncompressPreloadedImages", &psUncompressPreloadedImages,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psRasterResolution")) {
+ parseFloat("psRasterResolution", &psRasterResolution,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psRasterMono")) {
+ parseYesNo("psRasterMono", &psRasterMono, tokens, fileName, line);
+ } else if (!cmd->cmp("psAlwaysRasterize")) {
+ parseYesNo("psAlwaysRasterize", &psAlwaysRasterize,
+ tokens, fileName, line);
} else if (!cmd->cmp("textEncoding")) {
parseTextEncoding(tokens, fileName, line);
} else if (!cmd->cmp("textEOL")) {
@@ -1044,8 +1075,6 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int 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")) {
@@ -1054,11 +1083,17 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
} else if (!cmd->cmp("enableFreeType")) {
parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
+ } else if (!cmd->cmp("disableFreeTypeHinting")) {
+ parseYesNo("disableFreeTypeHinting", &disableFreeTypeHinting,
+ 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("antialiasPrinting")) {
+ parseYesNo("antialiasPrinting", &antialiasPrinting,
+ tokens, fileName, line);
} else if (!cmd->cmp("strokeAdjust")) {
parseYesNo("strokeAdjust", &strokeAdjust, tokens, fileName, line);
} else if (!cmd->cmp("screenType")) {
@@ -1077,6 +1112,17 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
} else if (!cmd->cmp("screenWhiteThreshold")) {
parseFloat("screenWhiteThreshold", &screenWhiteThreshold,
tokens, fileName, line);
+ } else if (!cmd->cmp("minLineWidth")) {
+ parseFloat("minLineWidth", &minLineWidth,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("drawAnnotations")) {
+ parseYesNo("drawAnnotations", &drawAnnotations,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("overprintPreview")) {
+ parseYesNo("overprintPreview", &overprintPreview,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("launchCommand")) {
+ parseCommand("launchCommand", &launchCommand, tokens, fileName, line);
} else if (!cmd->cmp("urlCommand")) {
parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
} else if (!cmd->cmp("movieCommand")) {
@@ -1096,17 +1142,18 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int 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);
+ error(errConfig, -1, "Unknown config file command '{0:t}' ({1:t}:{2:d})",
+ cmd, fileName, line);
if (!cmd->cmp("displayFontX") ||
!cmd->cmp("displayNamedCIDFontX") ||
!cmd->cmp("displayCIDFontX")) {
- error(-1, "-- Xpdf no longer supports X fonts");
+ error(errConfig, -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");
+ error(errConfig, -1,
+ "The t1libControl and freetypeControl options have been replaced 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(errConfig, -1,
+ "The config file format has changed since Xpdf 0.9x");
}
}
}
@@ -1115,7 +1162,7 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
}
void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
- int line) {
+ int line) {
GString *name;
char *tok1, *tok2;
FILE *f;
@@ -1124,14 +1171,14 @@ void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
Unicode u;
if (tokens->getLength() != 2) {
- error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'nameToUnicode' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
name = (GString *)tokens->get(1);
- if (!(f = fopen(name->getCString(), "r"))) {
- error(-1, "Couldn't open 'nameToUnicode' file '%s'",
- name->getCString());
+ if (!(f = openFile(name->getCString(), "r"))) {
+ error(errConfig, -1, "Couldn't open 'nameToUnicode' file '{0:t}'", name);
return;
}
line2 = 1;
@@ -1142,7 +1189,8 @@ void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
sscanf(tok1, "%x", &u);
nameToUnicode->add(tok2, u);
} else {
- error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
+ error(errConfig, -1, "Bad line in 'nameToUnicode' file ({0:t}:{1:d})",
+ name, line2);
}
++line2;
}
@@ -1154,8 +1202,9 @@ void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
GString *collection, *name, *old;
if (tokens->getLength() != 3) {
- error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'cidToUnicode' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
collection = (GString *)tokens->get(1);
@@ -1171,8 +1220,9 @@ void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
GString *font, *file, *old;
if (tokens->getLength() != 3) {
- error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'unicodeToUnicode' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
font = (GString *)tokens->get(1);
@@ -1188,8 +1238,8 @@ void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
GString *encodingName, *name, *old;
if (tokens->getLength() != 3) {
- error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'unicodeMap' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
encodingName = (GString *)tokens->get(1);
@@ -1205,8 +1255,8 @@ void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
GList *list;
if (tokens->getLength() != 3) {
- error(-1, "Bad 'cMapDir' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'cMapDir' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
collection = (GString *)tokens->get(1);
@@ -1221,49 +1271,54 @@ void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
int line) {
if (tokens->getLength() != 2) {
- error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'toUnicodeDir' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
}
-void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
- DisplayFontParamKind kind,
- GString *fileName, int line) {
- DisplayFontParam *param, *old;
-
- if (tokens->getLength() < 2) {
- goto err1;
+void GlobalParams::parseFontFile(GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 3) {
+ error(errConfig, -1, "Bad 'fontFile' config file command ({0:t}:{1:d})",
+ fileName, line);
+ return;
}
- param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
-
- switch (kind) {
- case displayFontT1:
- if (tokens->getLength() != 3) {
- goto err2;
- }
- param->t1.fileName = ((GString *)tokens->get(2))->copy();
- break;
- case displayFontTT:
- if (tokens->getLength() != 3) {
- goto err2;
- }
- param->tt.fileName = ((GString *)tokens->get(2))->copy();
- break;
+ fontFiles->add(((GString *)tokens->get(1))->copy(),
+ ((GString *)tokens->get(2))->copy());
+}
+
+void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(errConfig, -1, "Bad 'fontDir' config file command ({0:t}:{1:d})",
+ fileName, line);
+ return;
}
+ fontDirs->append(((GString *)tokens->get(1))->copy());
+}
- if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
- delete old;
+void GlobalParams::parseFontFileCC(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 3) {
+ error(errConfig, -1, "Bad 'fontFileCC' config file command ({0:t}:{1:d})",
+ fileName, line);
+ return;
}
- fontHash->add(param->name, param);
- return;
+ ccFontFiles->add(((GString *)tokens->get(1))->copy(),
+ ((GString *)tokens->get(2))->copy());
+}
- err2:
- delete param;
- err1:
- error(-1, "Bad 'display*Font*' config file command (%s:%d)",
- fileName->getCString(), line);
+void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(errConfig, -1, "Bad 'psFile' config file command ({0:t}:{1:d})",
+ fileName, line);
+ return;
+ }
+ if (psFile) {
+ delete psFile;
+ }
+ psFile = ((GString *)tokens->get(1))->copy();
}
void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
@@ -1273,8 +1328,9 @@ void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
if (tokens->getLength() == 2) {
tok = (GString *)tokens->get(1);
if (!setPSPaperSize(tok->getCString())) {
- error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'psPaperSize' config file command ({0:s}:{1:d})",
+ fileName, line);
}
} else if (tokens->getLength() == 3) {
tok = (GString *)tokens->get(1);
@@ -1285,16 +1341,17 @@ void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
psImageableURX = psPaperWidth;
psImageableURY = psPaperHeight;
} else {
- error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'psPaperSize' config file command ({0:t}:{1:d})",
+ fileName, line);
}
}
void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
int line) {
if (tokens->getLength() != 5) {
- error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'psImageableArea' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
@@ -1307,8 +1364,8 @@ void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
- error(-1, "Bad 'psLevel' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
tok = (GString *)tokens->get(1);
@@ -1325,45 +1382,59 @@ void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
} else if (!tok->cmp("level3Sep")) {
psLevel = psLevel3Sep;
} else {
- error(-1, "Bad 'psLevel' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})",
+ fileName, line);
}
}
-void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'psFile' config file command (%s:%d)",
- fileName->getCString(), line);
+void GlobalParams::parsePSResidentFont(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 3) {
+ error(errConfig, -1, "Bad 'psResidentFont' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
- if (psFile) {
- delete psFile;
- }
- psFile = ((GString *)tokens->get(1))->copy();
+ psResidentFonts->add(((GString *)tokens->get(1))->copy(),
+ ((GString *)tokens->get(2))->copy());
}
-void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
- PSFontParam *param;
+void GlobalParams::parsePSResidentFont16(GList *tokens, GString *fileName,
+ int line) {
+ PSFontParam16 *param;
+ int wMode;
+ GString *tok;
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'psFont' config file command (%s:%d)",
- fileName->getCString(), line);
+ if (tokens->getLength() != 5) {
+ error(errConfig, -1, "Bad 'psResidentFont16' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
- param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
- ((GString *)tokens->get(2))->copy(), NULL);
- psFonts->add(param->pdfFontName, param);
+ tok = (GString *)tokens->get(2);
+ if (!tok->cmp("H")) {
+ wMode = 0;
+ } else if (!tok->cmp("V")) {
+ wMode = 1;
+ } else {
+ error(errConfig, -1, "Bad wMode in psResidentFont16 config file command ({1:t}:{2:d})",
+ fileName, line);
+ return;
+ }
+ param = new PSFontParam16(((GString *)tokens->get(1))->copy(),
+ wMode,
+ ((GString *)tokens->get(3))->copy(),
+ ((GString *)tokens->get(4))->copy());
+ psResidentFonts16->append(param);
}
-void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
- GList *tokens, GString *fileName, int line) {
- PSFontParam *param;
+void GlobalParams::parsePSResidentFontCC(GList *tokens, GString *fileName,
+ int line) {
+ PSFontParam16 *param;
int wMode;
GString *tok;
if (tokens->getLength() != 5) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'psResidentFontCC' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
tok = (GString *)tokens->get(2);
@@ -1372,22 +1443,23 @@ void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
} else if (!tok->cmp("V")) {
wMode = 1;
} else {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad wMode in psResidentFontCC config file command ({1:t}:{2:d})",
+ fileName, line);
return;
}
- param = new PSFontParam(((GString *)tokens->get(1))->copy(),
- wMode,
- ((GString *)tokens->get(3))->copy(),
- ((GString *)tokens->get(4))->copy());
- fontList->append(param);
+ param = new PSFontParam16(((GString *)tokens->get(1))->copy(),
+ wMode,
+ ((GString *)tokens->get(3))->copy(),
+ ((GString *)tokens->get(4))->copy());
+ psResidentFontsCC->append(param);
}
void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
int line) {
if (tokens->getLength() != 2) {
- error(-1, "Bad 'textEncoding' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad 'textEncoding' config file command ({0:s}:{1:d})",
+ fileName, line);
return;
}
delete textEncoding;
@@ -1398,8 +1470,8 @@ void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
- error(-1, "Bad 'textEOL' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
tok = (GString *)tokens->get(1);
@@ -1410,25 +1482,16 @@ void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
} else if (!tok->cmp("mac")) {
textEOL = eolMac;
} else {
- error(-1, "Bad 'textEOL' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})",
+ fileName, line);
}
}
-void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'fontDir' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- fontDirs->append(((GString *)tokens->get(1))->copy());
-}
-
void GlobalParams::parseInitialZoom(GList *tokens,
GString *fileName, int line) {
if (tokens->getLength() != 2) {
- error(-1, "Bad 'initialZoom' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'initialZoom' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
delete initialZoom;
@@ -1440,8 +1503,8 @@ void GlobalParams::parseScreenType(GList *tokens, GString *fileName,
GString *tok;
if (tokens->getLength() != 2) {
- error(-1, "Bad 'screenType' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
tok = (GString *)tokens->get(1);
@@ -1452,8 +1515,8 @@ void GlobalParams::parseScreenType(GList *tokens, GString *fileName,
} else if (!tok->cmp("stochasticClustered")) {
screenType = screenStochasticClustered;
} else {
- error(-1, "Bad 'screenType' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})",
+ fileName, line);
}
}
@@ -1463,8 +1526,8 @@ void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) {
int code, mods, context, i;
if (tokens->getLength() < 4) {
- error(-1, "Bad 'bind' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'bind' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
@@ -1493,8 +1556,8 @@ void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) {
int code, mods, context, i;
if (tokens->getLength() != 3) {
- error(-1, "Bad 'unbind' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(errConfig, -1, "Bad 'unbind' config file command ({0:t}:{1:d})",
+ fileName, line);
return;
}
if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
@@ -1515,9 +1578,10 @@ void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) {
GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
int *code, int *mods, int *context,
- char *cmdName,
+ const char *cmdName,
GList *tokens, GString *fileName, int line) {
char *p0;
+ int btn;
*mods = xpdfKeyModNone;
p0 = modKeyStr->getCString();
@@ -1574,16 +1638,21 @@ GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
!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');
+ p0[10] >= '0' && p0[10] <= '9' &&
+ (!p0[11] || (p0[11] >= '0' && p0[11] <= '9' && !p0[12])) &&
+ (btn = atoi(p0 + 10)) >= 1 && btn <= 32) {
+ *code = xpdfKeyCodeMousePress1 + btn - 1;
} else if (!strncmp(p0, "mouseRelease", 12) &&
- p0[12] >= '1' && p0[12] <= '7' && !p0[13]) {
- *code = xpdfKeyCodeMouseRelease1 + (p0[12] - '1');
+ p0[12] >= '0' && p0[12] <= '9' &&
+ (!p0[13] || (p0[13] >= '0' && p0[13] <= '9' && !p0[14])) &&
+ (btn = atoi(p0 + 12)) >= 1 && btn <= 32) {
+ *code = xpdfKeyCodeMouseRelease1 + btn - 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);
+ error(errConfig, -1,
+ "Bad key/modifier in '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return gFalse;
}
@@ -1624,16 +1693,18 @@ GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
*context |= xpdfKeyContextScrLockOff;
p0 += 10;
} else {
- error(-1, "Bad context in '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad context in '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return gFalse;
}
if (!*p0) {
break;
}
if (*p0 != ',') {
- error(-1, "Bad context in '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1,
+ "Bad context in '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return gFalse;
}
++p0;
@@ -1643,11 +1714,11 @@ GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
return gTrue;
}
-void GlobalParams::parseCommand(char *cmdName, GString **val,
+void GlobalParams::parseCommand(const char *cmdName, GString **val,
GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
if (*val) {
@@ -1656,19 +1727,19 @@ void GlobalParams::parseCommand(char *cmdName, GString **val,
*val = ((GString *)tokens->get(1))->copy();
}
-void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
+void GlobalParams::parseYesNo(const char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
tok = (GString *)tokens->get(1);
if (!parseYesNo2(tok->getCString(), flag)) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
}
}
@@ -1683,20 +1754,20 @@ GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
return gTrue;
}
-void GlobalParams::parseInteger(char *cmdName, int *val,
+void GlobalParams::parseInteger(const 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);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
tok = (GString *)tokens->get(1);
if (tok->getLength() == 0) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
if (tok->getChar(0) == '-') {
@@ -1706,28 +1777,28 @@ void GlobalParams::parseInteger(char *cmdName, int *val,
}
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);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
}
*val = atoi(tok->getCString());
}
-void GlobalParams::parseFloat(char *cmdName, double *val,
+void GlobalParams::parseFloat(const 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);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
tok = (GString *)tokens->get(1);
if (tok->getLength() == 0) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
if (tok->getChar(0) == '-') {
@@ -1738,8 +1809,8 @@ void GlobalParams::parseFloat(char *cmdName, double *val,
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);
+ error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
+ cmdName, fileName, line);
return;
}
}
@@ -1762,23 +1833,21 @@ GlobalParams::~GlobalParams() {
deleteGHash(residentUnicodeMaps, UnicodeMap);
deleteGHash(unicodeMaps, GString);
deleteGList(toUnicodeDirs, GString);
- deleteGHash(displayFonts, DisplayFontParam);
- deleteGHash(displayCIDFonts, DisplayFontParam);
- deleteGHash(displayNamedCIDFonts, DisplayFontParam);
-#ifdef WIN32
- if (winFontList) {
- delete winFontList;
- }
-#endif
+ deleteGHash(fontFiles, GString);
+ deleteGList(fontDirs, GString);
+ deleteGHash(ccFontFiles, GString);
+ delete sysFonts;
if (psFile) {
delete psFile;
}
- deleteGHash(psFonts, PSFontParam);
- deleteGList(psNamedFonts16, PSFontParam);
- deleteGList(psFonts16, PSFontParam);
+ deleteGHash(psResidentFonts, GString);
+ deleteGList(psResidentFonts16, PSFontParam16);
+ deleteGList(psResidentFontsCC, PSFontParam16);
delete textEncoding;
- deleteGList(fontDirs, GString);
delete initialZoom;
+ if (launchCommand) {
+ delete launchCommand;
+ }
if (urlCommand) {
delete urlCommand;
}
@@ -1829,8 +1898,6 @@ void GlobalParams::setupBaseFonts(char *dir) {
char winFontDir[MAX_PATH];
#endif
FILE *f;
- DisplayFontParamKind kind;
- DisplayFontParam *dfp;
int i, j;
#ifdef WIN32
@@ -1850,16 +1917,13 @@ void GlobalParams::setupBaseFonts(char *dir) {
}
#endif
for (i = 0; displayFontTab[i].name; ++i) {
- fontName = new GString(displayFontTab[i].name);
- if (getDisplayFont(fontName)) {
- delete fontName;
+ if (fontFiles->lookup(displayFontTab[i].name)) {
continue;
}
+ fontName = new GString(displayFontTab[i].name);
fileName = NULL;
- kind = displayFontT1; // make gcc happy
if (dir) {
fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
- kind = displayFontT1;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
@@ -1871,7 +1935,6 @@ void GlobalParams::setupBaseFonts(char *dir) {
if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
fileName = appendToPath(new GString(winFontDir),
displayFontTab[i].ttFileName);
- kind = displayFontTT;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
@@ -1886,7 +1949,6 @@ void GlobalParams::setupBaseFonts(char *dir) {
for (j = 0; !fileName && displayFontDirs[j]; ++j) {
fileName = appendToPath(new GString(displayFontDirs[j]),
displayFontTab[i].ttFileName);
- kind = displayFontTT;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
@@ -1895,11 +1957,10 @@ void GlobalParams::setupBaseFonts(char *dir) {
}
}
}
-#else
+#else // WIN32
for (j = 0; !fileName && displayFontDirs[j]; ++j) {
fileName = appendToPath(new GString(displayFontDirs[j]),
displayFontTab[i].t1FileName);
- kind = displayFontT1;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
@@ -1907,20 +1968,19 @@ void GlobalParams::setupBaseFonts(char *dir) {
fileName = NULL;
}
}
-#endif
+#endif // WIN32
if (!fileName) {
- error(-1, "No display font for '%s'", displayFontTab[i].name);
+ error(errConfig, -1, "No display font for '{0:s}'",
+ displayFontTab[i].name);
delete fontName;
continue;
}
- dfp = new DisplayFontParam(fontName, kind);
- dfp->t1.fileName = fileName;
- globalParams->addDisplayFont(dfp);
+ addFontFile(fontName, fileName);
}
#ifdef WIN32
if (winFontDir[0]) {
- winFontList = new WinFontList(winFontDir);
+ sysFonts->scanWindowsFonts(winFontDir);
}
#endif
}
@@ -1943,7 +2003,7 @@ GString *GlobalParams::getBaseDir() {
return s;
}
-Unicode GlobalParams::mapNameToUnicode(char *charName) {
+Unicode GlobalParams::mapNameToUnicode(const char *charName) {
// no need to lock - nameToUnicode is constant
return nameToUnicode->lookup(charName);
}
@@ -1966,7 +2026,7 @@ FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
lockGlobalParams;
if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
- f = fopen(fileName->getCString(), "r");
+ f = openFile(fileName->getCString(), "r");
} else {
f = NULL;
}
@@ -1989,7 +2049,7 @@ FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
for (i = 0; i < list->getLength(); ++i) {
dir = (GString *)list->get(i);
fileName = appendToPath(dir->copy(), cMapName->getCString());
- f = fopen(fileName->getCString(), "r");
+ f = openFile(fileName->getCString(), "r");
delete fileName;
if (f) {
unlockGlobalParams;
@@ -2009,7 +2069,7 @@ FILE *GlobalParams::findToUnicodeFile(GString *name) {
for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
dir = (GString *)toUnicodeDirs->get(i);
fileName = appendToPath(dir->copy(), name->getCString());
- f = fopen(fileName->getCString(), "r");
+ f = openFile(fileName->getCString(), "r");
delete fileName;
if (f) {
unlockGlobalParams;
@@ -2020,31 +2080,72 @@ FILE *GlobalParams::findToUnicodeFile(GString *name) {
return NULL;
}
-DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
- DisplayFontParam *dfp;
+GString *GlobalParams::findFontFile(GString *fontName) {
+ static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc" };
+ GString *path, *dir;
+#ifdef WIN32
+ GString *fontNameU;
+#endif
+ const char *ext;
+ FILE *f;
+ int i, j;
lockGlobalParams;
- dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
-#ifdef WIN32
- if (!dfp && winFontList) {
- dfp = winFontList->find(fontName);
+ if ((path = (GString *)fontFiles->lookup(fontName))) {
+ path = path->copy();
+ unlockGlobalParams;
+ return path;
}
+ for (i = 0; i < fontDirs->getLength(); ++i) {
+ dir = (GString *)fontDirs->get(i);
+ for (j = 0; j < (int)(sizeof(exts) / sizeof(exts[0])); ++j) {
+ ext = exts[j];
+#ifdef WIN32
+ fontNameU = fileNameToUTF8(fontName->getCString());
+ path = appendToPath(dir->copy(), fontNameU->getCString());
+ delete fontNameU;
+#else
+ path = appendToPath(dir->copy(), fontName->getCString());
#endif
+ path->append(ext);
+ if ((f = openFile(path->getCString(), "rb"))) {
+ fclose(f);
+ unlockGlobalParams;
+ return path;
+ }
+ delete path;
+ }
+ }
unlockGlobalParams;
- return dfp;
+ return NULL;
}
-DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
- GString *collection) {
- DisplayFontParam *dfp;
+GString *GlobalParams::findSystemFontFile(GString *fontName,
+ SysFontType *type,
+ int *fontNum) {
+ SysFontInfo *fi;
+ GString *path;
+ path = NULL;
lockGlobalParams;
- if (!fontName ||
- !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
- dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
+ if ((fi = sysFonts->find(fontName))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
}
unlockGlobalParams;
- return dfp;
+ return path;
+}
+
+GString *GlobalParams::findCCFontFile(GString *collection) {
+ GString *path;
+
+ lockGlobalParams;
+ if ((path = (GString *)ccFontFiles->lookup(collection))) {
+ path = path->copy();
+ }
+ unlockGlobalParams;
+ return path;
}
GString *GlobalParams::getPSFile() {
@@ -2137,41 +2238,62 @@ PSLevel GlobalParams::getPSLevel() {
return level;
}
-PSFontParam *GlobalParams::getPSFont(GString *fontName) {
- PSFontParam *p;
+GString *GlobalParams::getPSResidentFont(GString *fontName) {
+ GString *psName;
lockGlobalParams;
- p = (PSFontParam *)psFonts->lookup(fontName);
+ psName = (GString *)psResidentFonts->lookup(fontName);
unlockGlobalParams;
- return p;
+ return psName;
}
-PSFontParam *GlobalParams::getPSFont16(GString *fontName,
- GString *collection, int wMode) {
- PSFontParam *p;
+GList *GlobalParams::getPSResidentFonts() {
+ GList *names;
+ GHashIter *iter;
+ GString *name;
+ GString *psName;
+
+ names = new GList();
+ lockGlobalParams;
+ psResidentFonts->startIter(&iter);
+ while (psResidentFonts->getNext(&iter, &name, (void **)&psName)) {
+ names->append(psName->copy());
+ }
+ unlockGlobalParams;
+ return names;
+}
+
+PSFontParam16 *GlobalParams::getPSResidentFont16(GString *fontName,
+ int wMode) {
+ PSFontParam16 *p;
int i;
lockGlobalParams;
p = NULL;
- if (fontName) {
- for (i = 0; i < psNamedFonts16->getLength(); ++i) {
- p = (PSFontParam *)psNamedFonts16->get(i);
- if (!p->pdfFontName->cmp(fontName) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
+ for (i = 0; i < psResidentFonts16->getLength(); ++i) {
+ p = (PSFontParam16 *)psResidentFonts16->get(i);
+ if (!(p->name->cmp(fontName)) && p->wMode == wMode) {
+ break;
}
+ p = NULL;
}
- if (!p && collection) {
- for (i = 0; i < psFonts16->getLength(); ++i) {
- p = (PSFontParam *)psFonts16->get(i);
- if (!p->pdfFontName->cmp(collection) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
+ unlockGlobalParams;
+ return p;
+}
+
+PSFontParam16 *GlobalParams::getPSResidentFontCC(GString *collection,
+ int wMode) {
+ PSFontParam16 *p;
+ int i;
+
+ lockGlobalParams;
+ p = NULL;
+ for (i = 0; i < psResidentFontsCC->getLength(); ++i) {
+ p = (PSFontParam16 *)psResidentFontsCC->get(i);
+ if (!(p->name->cmp(collection)) && p->wMode == wMode) {
+ break;
}
+ p = NULL;
}
unlockGlobalParams;
return p;
@@ -2213,6 +2335,15 @@ GBool GlobalParams::getPSEmbedCIDTrueType() {
return e;
}
+GBool GlobalParams::getPSFontPassthrough() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psFontPassthrough;
+ unlockGlobalParams;
+ return e;
+}
+
GBool GlobalParams::getPSPreload() {
GBool preload;
@@ -2240,6 +2371,42 @@ GBool GlobalParams::getPSASCIIHex() {
return ah;
}
+GBool GlobalParams::getPSUncompressPreloadedImages() {
+ GBool ah;
+
+ lockGlobalParams;
+ ah = psUncompressPreloadedImages;
+ unlockGlobalParams;
+ return ah;
+}
+
+double GlobalParams::getPSRasterResolution() {
+ double res;
+
+ lockGlobalParams;
+ res = psRasterResolution;
+ unlockGlobalParams;
+ return res;
+}
+
+GBool GlobalParams::getPSRasterMono() {
+ GBool mono;
+
+ lockGlobalParams;
+ mono = psRasterMono;
+ unlockGlobalParams;
+ return mono;
+}
+
+GBool GlobalParams::getPSAlwaysRasterize() {
+ GBool rast;
+
+ lockGlobalParams;
+ rast = psAlwaysRasterize;
+ unlockGlobalParams;
+ return rast;
+}
+
GString *GlobalParams::getTextEncodingName() {
GString *s;
@@ -2276,30 +2443,6 @@ GBool GlobalParams::getTextKeepTinyChars() {
return tiny;
}
-GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
- GString *dir, *fileName;
- char **ext;
- FILE *f;
- int i;
-
- lockGlobalParams;
- for (i = 0; i < fontDirs->getLength(); ++i) {
- dir = (GString *)fontDirs->get(i);
- for (ext = exts; *ext; ++ext) {
- fileName = appendToPath(dir->copy(), fontName->getCString());
- fileName->append(*ext);
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- unlockGlobalParams;
- return fileName;
- }
- delete fileName;
- }
- }
- unlockGlobalParams;
- return NULL;
-}
-
GString *GlobalParams::getInitialZoom() {
GString *s;
@@ -2336,6 +2479,15 @@ GBool GlobalParams::getEnableFreeType() {
return f;
}
+GBool GlobalParams::getDisableFreeTypeHinting() {
+ GBool f;
+
+ lockGlobalParams;
+ f = disableFreeTypeHinting;
+ unlockGlobalParams;
+ return f;
+}
+
GBool GlobalParams::getAntialias() {
GBool f;
@@ -2355,6 +2507,15 @@ GBool GlobalParams::getVectorAntialias() {
return f;
}
+GBool GlobalParams::getAntialiasPrinting() {
+ GBool f;
+
+ lockGlobalParams;
+ f = antialiasPrinting;
+ unlockGlobalParams;
+ return f;
+}
+
GBool GlobalParams::getStrokeAdjust() {
GBool f;
@@ -2418,6 +2579,24 @@ double GlobalParams::getScreenWhiteThreshold() {
return thresh;
}
+double GlobalParams::getMinLineWidth() {
+ double w;
+
+ lockGlobalParams;
+ w = minLineWidth;
+ unlockGlobalParams;
+ return w;
+}
+
+GBool GlobalParams::getDrawAnnotations() {
+ GBool draw;
+
+ lockGlobalParams;
+ draw = drawAnnotations;
+ unlockGlobalParams;
+ return draw;
+}
+
GBool GlobalParams::getMapNumericCharNames() {
GBool map;
@@ -2552,14 +2731,9 @@ UnicodeMap *GlobalParams::getTextEncoding() {
// functions to set parameters
//------------------------------------------------------------------------
-void GlobalParams::addDisplayFont(DisplayFontParam *param) {
- DisplayFontParam *old;
-
+void GlobalParams::addFontFile(GString *fontName, GString *path) {
lockGlobalParams;
- if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
- delete old;
- }
- displayFonts->add(param->name, param);
+ fontFiles->add(fontName, path);
unlockGlobalParams;
}
@@ -2684,6 +2858,12 @@ void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
unlockGlobalParams;
}
+void GlobalParams::setPSFontPassthrough(GBool passthrough) {
+ lockGlobalParams;
+ psFontPassthrough = passthrough;
+ unlockGlobalParams;
+}
+
void GlobalParams::setPSPreload(GBool preload) {
lockGlobalParams;
psPreload = preload;
diff --git a/xpdf/GlobalParams.h b/xpdf/GlobalParams.h
index 7fa26ca..e2da5ca 100644
--- a/xpdf/GlobalParams.h
+++ b/xpdf/GlobalParams.h
@@ -35,9 +35,7 @@ class CMap;
class CMapCache;
struct XpdfSecurityHandler;
class GlobalParams;
-#ifdef WIN32
-class WinFontList;
-#endif
+class SysFontList;
//------------------------------------------------------------------------
@@ -46,51 +44,27 @@ extern GlobalParams *globalParams;
//------------------------------------------------------------------------
-enum DisplayFontParamKind {
- displayFontT1,
- displayFontTT
-};
-
-struct DisplayFontParamT1 {
- GString *fileName;
-};
-
-struct DisplayFontParamTT {
- GString *fileName;
-};
-
-class DisplayFontParam {
-public:
-
- GString *name; // font name for 8-bit fonts and named
- // CID fonts; collection name for
- // generic CID fonts
- DisplayFontParamKind kind;
- union {
- DisplayFontParamT1 t1;
- DisplayFontParamTT tt;
- };
-
- DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
- virtual ~DisplayFontParam();
+enum SysFontType {
+ sysFontPFA,
+ sysFontPFB,
+ sysFontTTF,
+ sysFontTTC
};
//------------------------------------------------------------------------
-class PSFontParam {
+class PSFontParam16 {
public:
- GString *pdfFontName; // PDF font name for 8-bit fonts and
- // named 16-bit fonts; char collection
- // name for generic 16-bit fonts
- int wMode; // writing mode (0=horiz, 1=vert) for
- // 16-bit fonts
+ GString *name; // PDF font name for psResidentFont16;
+ // char collection name for psResidentFontCC
+ int wMode; // writing mode (0=horiz, 1=vert)
GString *psFontName; // PostScript font name
- GString *encoding; // encoding, for 16-bit fonts only
+ GString *encoding; // encoding
- PSFontParam(GString *pdfFontNameA, int wModeA,
- GString *psFontNameA, GString *encodingA);
- ~PSFontParam();
+ PSFontParam16(GString *nameA, int wModeA,
+ GString *psFontNameA, GString *encodingA);
+ ~PSFontParam16();
};
//------------------------------------------------------------------------
@@ -135,8 +109,9 @@ public:
// 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, const char *cmd0);
+ KeyBinding(int codeA, int modsA, int contextA,
+ const char *cmd0, const char *cmd1);
KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA);
~KeyBinding();
};
@@ -164,6 +139,8 @@ public:
#define xpdfKeyCodeMousePress5 0x2005
#define xpdfKeyCodeMousePress6 0x2006
#define xpdfKeyCodeMousePress7 0x2007
+// ...
+#define xpdfKeyCodeMousePress32 0x2020
#define xpdfKeyCodeMouseRelease1 0x2101
#define xpdfKeyCodeMouseRelease2 0x2102
#define xpdfKeyCodeMouseRelease3 0x2103
@@ -171,6 +148,8 @@ public:
#define xpdfKeyCodeMouseRelease5 0x2105
#define xpdfKeyCodeMouseRelease6 0x2106
#define xpdfKeyCodeMouseRelease7 0x2107
+// ...
+#define xpdfKeyCodeMouseRelease32 0x2120
#define xpdfKeyModNone 0
#define xpdfKeyModShift (1 << 0)
#define xpdfKeyModCtrl (1 << 1)
@@ -208,13 +187,15 @@ public:
CharCode getMacRomanCharCode(char *charName);
GString *getBaseDir();
- Unicode mapNameToUnicode(char *charName);
+ Unicode mapNameToUnicode(const char *charName);
UnicodeMap *getResidentUnicodeMap(GString *encodingName);
FILE *getUnicodeMapFile(GString *encodingName);
FILE *findCMapFile(GString *collection, GString *cMapName);
FILE *findToUnicodeFile(GString *name);
- DisplayFontParam *getDisplayFont(GString *fontName);
- DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
+ GString *findFontFile(GString *fontName);
+ GString *findSystemFontFile(GString *fontName, SysFontType *type,
+ int *fontNum);
+ GString *findCCFontFile(GString *collection);
GString *getPSFile();
int getPSPaperWidth();
int getPSPaperHeight();
@@ -225,26 +206,34 @@ public:
GBool getPSShrinkLarger();
GBool getPSCenter();
PSLevel getPSLevel();
- PSFontParam *getPSFont(GString *fontName);
- PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
+ GString *getPSResidentFont(GString *fontName);
+ GList *getPSResidentFonts();
+ PSFontParam16 *getPSResidentFont16(GString *fontName, int wMode);
+ PSFontParam16 *getPSResidentFontCC(GString *collection, int wMode);
GBool getPSEmbedType1();
GBool getPSEmbedTrueType();
GBool getPSEmbedCIDPostScript();
GBool getPSEmbedCIDTrueType();
+ GBool getPSFontPassthrough();
GBool getPSPreload();
GBool getPSOPI();
GBool getPSASCIIHex();
+ GBool getPSUncompressPreloadedImages();
+ double getPSRasterResolution();
+ GBool getPSRasterMono();
+ GBool getPSAlwaysRasterize();
GString *getTextEncodingName();
EndOfLineKind getTextEOL();
GBool getTextPageBreaks();
GBool getTextKeepTinyChars();
- GString *findFontFile(GString *fontName, char **exts);
GString *getInitialZoom();
GBool getContinuousView();
GBool getEnableT1lib();
GBool getEnableFreeType();
+ GBool getDisableFreeTypeHinting();
GBool getAntialias();
GBool getVectorAntialias();
+ GBool getAntialiasPrinting();
GBool getStrokeAdjust();
ScreenType getScreenType();
int getScreenSize();
@@ -252,6 +241,10 @@ public:
double getScreenGamma();
double getScreenBlackThreshold();
double getScreenWhiteThreshold();
+ double getMinLineWidth();
+ GBool getDrawAnnotations();
+ GBool getOverprintPreview() { return overprintPreview; }
+ GString *getLaunchCommand() { return launchCommand; }
GString *getURLCommand() { return urlCommand; }
GString *getMovieCommand() { return movieCommand; }
GBool getMapNumericCharNames();
@@ -268,7 +261,7 @@ public:
//----- functions to set parameters
- void addDisplayFont(DisplayFontParam *param);
+ void addFontFile(GString *fontName, GString *path);
void setPSFile(char *file);
GBool setPSPaperSize(char *size);
void setPSPaperWidth(int width);
@@ -284,6 +277,7 @@ public:
void setPSEmbedTrueType(GBool embed);
void setPSEmbedCIDPostScript(GBool embed);
void setPSEmbedCIDTrueType(GBool embed);
+ void setPSFontPassthrough(GBool passthrough);
void setPSPreload(GBool preload);
void setPSOPI(GBool opi);
void setPSASCIIHex(GBool hex);
@@ -323,35 +317,35 @@ private:
void parseUnicodeMap(GList *tokens, GString *fileName, int line);
void parseCMapDir(GList *tokens, GString *fileName, int line);
void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
- void parseDisplayFont(GList *tokens, GHash *fontHash,
- DisplayFontParamKind kind,
- GString *fileName, int line);
+ void parseFontFile(GList *tokens, GString *fileName, int line);
+ void parseFontDir(GList *tokens, GString *fileName, int line);
+ void parseFontFileCC(GList *tokens, GString *fileName,
+ int line);
void parsePSFile(GList *tokens, GString *fileName, int line);
void parsePSPaperSize(GList *tokens, GString *fileName, int line);
void parsePSImageableArea(GList *tokens, GString *fileName, int line);
void parsePSLevel(GList *tokens, GString *fileName, int line);
- void parsePSFont(GList *tokens, GString *fileName, int line);
- void parsePSFont16(char *cmdName, GList *fontList,
- GList *tokens, GString *fileName, int line);
+ void parsePSResidentFont(GList *tokens, GString *fileName, int line);
+ void parsePSResidentFont16(GList *tokens, GString *fileName, int line);
+ void parsePSResidentFontCC(GList *tokens, GString *fileName, int line);
void parseTextEncoding(GList *tokens, GString *fileName, int line);
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);
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,
+ const char *cmdName,
GList *tokens, GString *fileName, int line);
- void parseCommand(char *cmdName, GString **val,
+ void parseCommand(const char *cmdName, GString **val,
GList *tokens, GString *fileName, int line);
- void parseYesNo(char *cmdName, GBool *flag,
+ void parseYesNo(const char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line);
GBool parseYesNo2(char *token, GBool *flag);
- void parseInteger(char *cmdName, int *val,
+ void parseInteger(const char *cmdName, int *val,
GList *tokens, GString *fileName, int line);
- void parseFloat(char *cmdName, double *val,
+ void parseFloat(const char *cmdName, double *val,
GList *tokens, GString *fileName, int line);
UnicodeMap *getUnicodeMap2(GString *encodingName);
#ifdef ENABLE_PLUGINS
@@ -380,15 +374,12 @@ private:
GHash *cMapDirs; // list of CMap dirs, indexed by collection
// name [GList[GString]]
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
- // font name [DisplayFontParam]
+ GHash *fontFiles; // font files: font name mapped to path
+ // [GString]
+ GList *fontDirs; // list of font dirs [GString]
+ GHash *ccFontFiles; // character collection font files:
+ // collection name mapped to path [GString]
+ SysFontList *sysFonts; // system fonts
GString *psFile; // PostScript file or command (for xpdf)
int psPaperWidth; // paper size, in PostScript points, for
int psPaperHeight; // PostScript output
@@ -402,31 +393,44 @@ private:
GBool psCenter; // center pages on the paper
GBool psDuplex; // enable duplexing in PostScript?
PSLevel psLevel; // PostScript level to generate
- GHash *psFonts; // PostScript font info, indexed by PDF
- // font name [PSFontParam]
- GList *psNamedFonts16; // named 16-bit fonts [PSFontParam]
- GList *psFonts16; // generic 16-bit fonts [PSFontParam]
+ GHash *psResidentFonts; // 8-bit fonts resident in printer:
+ // PDF font name mapped to PS font name
+ // [GString]
+ GList *psResidentFonts16; // 16-bit fonts resident in printer:
+ // PDF font name mapped to font info
+ // [PSFontParam16]
+ GList *psResidentFontsCC; // 16-bit character collection fonts
+ // resident in printer: collection name
+ // mapped to font info [PSFontParam16]
GBool psEmbedType1; // embed Type 1 fonts?
GBool psEmbedTrueType; // embed TrueType fonts?
GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
+ GBool psFontPassthrough; // pass all fonts through as-is?
GBool psPreload; // preload PostScript images and forms into
// memory
GBool psOPI; // generate PostScript OPI comments?
GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
+ GBool psUncompressPreloadedImages; // uncompress all preloaded images
+ double psRasterResolution; // PostScript rasterization resolution (dpi)
+ GBool psRasterMono; // true to do PostScript rasterization
+ // in monochrome (gray); false to do it
+ // in color (RGB/CMYK)
+ GBool psAlwaysRasterize; // force PostScript rasterization
GString *textEncoding; // encoding (unicodeMap) to use for text
// output
EndOfLineKind textEOL; // type of EOL marker to use for text
// output
GBool textPageBreaks; // insert end-of-page markers?
GBool textKeepTinyChars; // keep all characters in text output
- GList *fontDirs; // list of font dirs [GString]
GString *initialZoom; // initial zoom level
GBool continuousView; // continuous view mode
GBool enableT1lib; // t1lib enable flag
GBool enableFreeType; // FreeType enable flag
+ GBool disableFreeTypeHinting; // FreeType hinting disable flag
GBool antialias; // font anti-aliasing enable flag
GBool vectorAntialias; // vector anti-aliasing enable flag
+ GBool antialiasPrinting; // allow anti-aliasing when printing
GBool strokeAdjust; // stroke adjustment enable flag
ScreenType screenType; // halftone screen type
int screenSize; // screen matrix size
@@ -434,6 +438,10 @@ private:
double screenGamma; // screen gamma correction
double screenBlackThreshold; // screen black clamping threshold
double screenWhiteThreshold; // screen white clamping threshold
+ double minLineWidth; // minimum line width
+ GBool drawAnnotations; // draw annotations or not
+ GBool overprintPreview; // enable overprint preview
+ GString *launchCommand; // command executed for 'launch' links
GString *urlCommand; // command executed for URL links
GString *movieCommand; // command executed for movie annotations
GBool mapNumericCharNames; // map numeric char names (from font subsets)?
diff --git a/xpdf/ImageOutputDev.cc b/xpdf/ImageOutputDev.cc
index 3c0f478..a5c9314 100644
--- a/xpdf/ImageOutputDev.cc
+++ b/xpdf/ImageOutputDev.cc
@@ -26,7 +26,7 @@
ImageOutputDev::ImageOutputDev(char *fileRootA, GBool dumpJPEGA) {
fileRoot = copyString(fileRootA);
- fileName = (char *)gmalloc(strlen(fileRoot) + 20);
+ fileName = (char *)gmalloc((int)strlen(fileRoot) + 20);
dumpJPEG = dumpJPEGA;
imgNum = 0;
ok = gTrue;
@@ -37,6 +37,14 @@ ImageOutputDev::~ImageOutputDev() {
gfree(fileRoot);
}
+void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep) {
+ // do nothing -- this avoids the potentially slow loop in Gfx.cc
+}
+
void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
@@ -51,7 +59,7 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
+ error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
@@ -73,7 +81,7 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
+ error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
fprintf(f, "P4\n");
@@ -115,7 +123,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
+ error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
@@ -138,7 +146,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
+ error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
fprintf(f, "P4\n");
@@ -163,7 +171,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
+ error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
fprintf(f, "P6\n");
@@ -179,13 +187,20 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
for (y = 0; y < height; ++y) {
// write the line
- p = imgStr->getLine();
- for (x = 0; x < width; ++x) {
- colorMap->getRGB(p, &rgb);
- fputc(colToByte(rgb.r), f);
- fputc(colToByte(rgb.g), f);
- fputc(colToByte(rgb.b), f);
- p += colorMap->getNumPixelComps();
+ if ((p = imgStr->getLine())) {
+ for (x = 0; x < width; ++x) {
+ colorMap->getRGB(p, &rgb);
+ fputc(colToByte(rgb.r), f);
+ fputc(colToByte(rgb.g), f);
+ fputc(colToByte(rgb.b), f);
+ p += colorMap->getNumPixelComps();
+ }
+ } else {
+ for (x = 0; x < width; ++x) {
+ fputc(0, f);
+ fputc(0, f);
+ fputc(0, f);
+ }
}
}
delete imgStr;
diff --git a/xpdf/ImageOutputDev.h b/xpdf/ImageOutputDev.h
index acc8a84..5496225 100644
--- a/xpdf/ImageOutputDev.h
+++ b/xpdf/ImageOutputDev.h
@@ -40,6 +40,11 @@ public:
// Check if file was successfully created.
virtual GBool isOk() { return ok; }
+ // Does this device use tilingPatternFill()? If this returns false,
+ // tiling pattern fills will be reduced to a series of other drawing
+ // operations.
+ virtual GBool useTilingPatternFill() { return gTrue; }
+
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gFalse; }
@@ -56,6 +61,13 @@ public:
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gFalse; }
+ //----- path painting
+ virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep);
+
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
diff --git a/xpdf/JArithmeticDecoder.cc b/xpdf/JArithmeticDecoder.cc
index 195b73e..56ddc31 100644
--- a/xpdf/JArithmeticDecoder.cc
+++ b/xpdf/JArithmeticDecoder.cc
@@ -91,6 +91,7 @@ JArithmeticDecoder::JArithmeticDecoder() {
str = NULL;
dataLen = 0;
limitStream = gFalse;
+ nBytesRead = 0;
}
inline Guint JArithmeticDecoder::readByte() {
@@ -100,6 +101,7 @@ inline Guint JArithmeticDecoder::readByte() {
return 0xff;
}
}
+ ++nBytesRead;
return (Guint)str->getChar() & 0xff;
}
@@ -120,14 +122,40 @@ void JArithmeticDecoder::start() {
}
void JArithmeticDecoder::restart(int dataLenA) {
- int oldDataLen;
-
- oldDataLen = dataLen;
- dataLen = dataLenA;
- if (oldDataLen == -1) {
+ Guint cAdd;
+ GBool prevFF;
+ int k, nBits;
+
+ if (dataLen >= 0) {
+ dataLen = dataLenA;
+ } else if (dataLen == -1) {
+ dataLen = dataLenA;
buf1 = readByte();
- } else if (oldDataLen <= -2) {
- buf0 = readByte();
+ } else {
+ k = (-dataLen - 1) * 8 - ct;
+ dataLen = dataLenA;
+ cAdd = 0;
+ prevFF = gFalse;
+ while (k > 0) {
+ buf0 = readByte();
+ if (prevFF) {
+ cAdd += 0xfe00 - (buf0 << 9);
+ nBits = 7;
+ } else {
+ cAdd += 0xff00 - (buf0 << 8);
+ nBits = 8;
+ }
+ prevFF = buf0 == 0xff;
+ if (k > nBits) {
+ cAdd <<= nBits;
+ k -= nBits;
+ } else {
+ cAdd <<= k;
+ ct = nBits - k;
+ k = 0;
+ }
+ }
+ c += cAdd;
buf1 = readByte();
}
}
@@ -306,6 +334,11 @@ Guint JArithmeticDecoder::decodeIAID(Guint codeLen,
void JArithmeticDecoder::byteIn() {
if (buf0 == 0xff) {
if (buf1 > 0x8f) {
+ if (limitStream) {
+ buf0 = buf1;
+ buf1 = readByte();
+ c = c + 0xff00 - (buf0 << 8);
+ }
ct = 8;
} else {
buf0 = buf1;
diff --git a/xpdf/JArithmeticDecoder.h b/xpdf/JArithmeticDecoder.h
index a40823d..7217984 100644
--- a/xpdf/JArithmeticDecoder.h
+++ b/xpdf/JArithmeticDecoder.h
@@ -84,6 +84,9 @@ public:
Guint decodeIAID(Guint codeLen,
JArithmeticDecoderStats *stats);
+ void resetByteCounter() { nBytesRead = 0; }
+ Guint getByteCounter() { return nBytesRead; }
+
private:
Guint readByte();
@@ -102,6 +105,7 @@ private:
Guint prev; // for the integer decoder
Stream *str;
+ Guint nBytesRead;
int dataLen;
GBool limitStream;
};
diff --git a/xpdf/JBIG2Stream.cc b/xpdf/JBIG2Stream.cc
index a4f1b6e..eb2719a 100644
--- a/xpdf/JBIG2Stream.cc
+++ b/xpdf/JBIG2Stream.cc
@@ -308,15 +308,20 @@ public:
// Sort the table by prefix length and assign prefix values.
void buildTable(JBIG2HuffmanTable *table, Guint len);
+ void resetByteCounter() { byteCounter = 0; }
+ Guint getByteCounter() { return byteCounter; }
+
private:
Stream *str;
Guint buf;
Guint bufLen;
+ Guint byteCounter;
};
JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
str = NULL;
+ byteCounter = 0;
reset();
}
@@ -371,10 +376,12 @@ Guint JBIG2HuffmanDecoder::readBits(Guint n) {
bufLen = 0;
while (nLeft >= 8) {
x = (x << 8) | (str->getChar() & 0xff);
+ ++byteCounter;
nLeft -= 8;
}
if (nLeft > 0) {
buf = str->getChar();
+ ++byteCounter;
bufLen = 8 - nLeft;
x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
}
@@ -385,6 +392,7 @@ Guint JBIG2HuffmanDecoder::readBits(Guint n) {
Guint JBIG2HuffmanDecoder::readBit() {
if (bufLen == 0) {
buf = str->getChar();
+ ++byteCounter;
bufLen = 8;
}
--bufLen;
@@ -422,12 +430,14 @@ void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
table[i] = table[len];
// assign prefixes
- i = 0;
- prefix = 0;
- table[i++].prefix = prefix++;
- for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
- prefix <<= table[i].prefixLen - table[i-1].prefixLen;
- table[i].prefix = prefix++;
+ if (table[0].rangeLen != jbig2HuffmanEOT) {
+ i = 0;
+ prefix = 0;
+ table[i++].prefix = prefix++;
+ for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
+ prefix <<= table[i].prefixLen - table[i-1].prefixLen;
+ table[i].prefix = prefix++;
+ }
}
}
@@ -446,6 +456,8 @@ public:
int getBlackCode();
int getWhiteCode();
Guint get24Bits();
+ void resetByteCounter() { byteCounter = 0; }
+ Guint getByteCounter() { return byteCounter; }
void skipTo(Guint length);
private:
@@ -454,10 +466,12 @@ private:
Guint buf;
Guint bufLen;
Guint nBytesRead;
+ Guint byteCounter;
};
JBIG2MMRDecoder::JBIG2MMRDecoder() {
str = NULL;
+ byteCounter = 0;
reset();
}
@@ -477,6 +491,7 @@ int JBIG2MMRDecoder::get2DCode() {
buf = str->getChar() & 0xff;
bufLen = 8;
++nBytesRead;
+ ++byteCounter;
p = &twoDimTab1[(buf >> 1) & 0x7f];
} else if (bufLen == 8) {
p = &twoDimTab1[(buf >> 1) & 0x7f];
@@ -486,12 +501,14 @@ int JBIG2MMRDecoder::get2DCode() {
buf = (buf << 8) | (str->getChar() & 0xff);
bufLen += 8;
++nBytesRead;
+ ++byteCounter;
p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
}
}
if (p->bits < 0) {
- error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
- return 0;
+ error(errSyntaxError, str->getPos(),
+ "Bad two dim code in JBIG2 MMR stream");
+ return EOF;
}
bufLen -= p->bits;
return p->n;
@@ -505,9 +522,10 @@ int JBIG2MMRDecoder::getWhiteCode() {
buf = str->getChar() & 0xff;
bufLen = 8;
++nBytesRead;
+ ++byteCounter;
}
while (1) {
- if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
+ if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
if (bufLen <= 12) {
code = buf << (12 - bufLen);
} else {
@@ -532,8 +550,9 @@ int JBIG2MMRDecoder::getWhiteCode() {
buf = (buf << 8) | (str->getChar() & 0xff);
bufLen += 8;
++nBytesRead;
+ ++byteCounter;
}
- error(str->getPos(), "Bad white code in JBIG2 MMR stream");
+ error(errSyntaxError, str->getPos(), "Bad white code in JBIG2 MMR stream");
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
--bufLen;
@@ -548,16 +567,18 @@ int JBIG2MMRDecoder::getBlackCode() {
buf = str->getChar() & 0xff;
bufLen = 8;
++nBytesRead;
+ ++byteCounter;
}
while (1) {
- if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
+ if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
if (bufLen <= 13) {
code = buf << (13 - bufLen);
} else {
code = buf >> (bufLen - 13);
}
p = &blackTab1[code & 0x7f];
- } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
+ } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 &&
+ ((buf >> (bufLen - 6)) & 0x03) != 0) {
if (bufLen <= 12) {
code = buf << (12 - bufLen);
} else {
@@ -582,8 +603,9 @@ int JBIG2MMRDecoder::getBlackCode() {
buf = (buf << 8) | (str->getChar() & 0xff);
bufLen += 8;
++nBytesRead;
+ ++byteCounter;
}
- error(str->getPos(), "Bad black code in JBIG2 MMR stream");
+ error(errSyntaxError, str->getPos(), "Bad black code in JBIG2 MMR stream");
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
--bufLen;
@@ -595,6 +617,7 @@ Guint JBIG2MMRDecoder::get24Bits() {
buf = (buf << 8) | (str->getChar() & 0xff);
bufLen += 8;
++nBytesRead;
+ ++byteCounter;
}
return (buf >> (bufLen - 24)) & 0xffffff;
}
@@ -603,6 +626,7 @@ void JBIG2MMRDecoder::skipTo(Guint length) {
while (nBytesRead < length) {
str->getChar();
++nBytesRead;
+ ++byteCounter;
}
}
@@ -654,6 +678,7 @@ public:
void clearToOne();
int getWidth() { return w; }
int getHeight() { return h; }
+ int getLineSize() { return line; }
int getPixel(int x, int y)
{ return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
(data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
@@ -683,8 +708,9 @@ JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
h = hA;
line = (wA + 7) >> 3;
if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
- data = NULL;
- return;
+ // force a call to gmalloc(-1), which will throw an exception
+ h = -1;
+ line = 2;
}
// need to allocate one extra guard byte for use in combine()
data = (Guchar *)gmalloc(h * line + 1);
@@ -698,8 +724,9 @@ JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
h = bitmap->h;
line = bitmap->line;
if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
- data = NULL;
- return;
+ // force a call to gmalloc(-1), which will throw an exception
+ h = -1;
+ line = 2;
}
// need to allocate one extra guard byte for use in combine()
data = (Guchar *)gmalloc(h * line + 1);
@@ -754,6 +781,8 @@ void JBIG2Bitmap::clearToOne() {
inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
if (y < 0 || y >= h || x >= w) {
ptr->p = NULL;
+ ptr->shift = 0; // make gcc happy
+ ptr->x = 0; // make gcc happy
} else if (x < 0) {
ptr->p = &data[y * line];
ptr->shift = 7;
@@ -798,6 +827,10 @@ void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
GBool oneByte;
+ // check for the pathological case where y = -2^31
+ if (y < -0x7fffffff) {
+ return;
+ }
if (y < 0) {
y0 = -y;
} else {
@@ -1011,8 +1044,13 @@ private:
JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
JBIG2Segment(segNumA)
{
+ Guint i;
+
size = sizeA;
bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
+ for (i = 0; i < size; ++i) {
+ bitmaps[i] = NULL;
+ }
genericRegionStats = NULL;
refinementRegionStats = NULL;
}
@@ -1021,7 +1059,9 @@ JBIG2SymbolDict::~JBIG2SymbolDict() {
Guint i;
for (i = 0; i < size; ++i) {
- delete bitmaps[i];
+ if (bitmaps[i]) {
+ delete bitmaps[i];
+ }
}
gfree(bitmaps);
if (genericRegionStats) {
@@ -1217,7 +1257,24 @@ int JBIG2Stream::lookChar() {
return EOF;
}
-GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
+int JBIG2Stream::getBlock(char *blk, int size) {
+ int n, i;
+
+ if (size <= 0) {
+ return 0;
+ }
+ if (dataEnd - dataPtr < size) {
+ n = (int)(dataEnd - dataPtr);
+ } else {
+ n = size;
+ }
+ for (i = 0; i < n; ++i) {
+ blk[i] = *dataPtr++ ^ 0xff;
+ }
+ return n;
+}
+
+GString *JBIG2Stream::getPSFilter(int psLevel, const char *indent) {
return NULL;
}
@@ -1254,7 +1311,9 @@ void JBIG2Stream::readSegments() {
refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
nRefSegs = refFlags & 0x1fffffff;
for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
- c1 = curStr->getChar();
+ if ((c1 = curStr->getChar()) == EOF) {
+ goto eofError1;
+ }
}
}
@@ -1296,7 +1355,19 @@ void JBIG2Stream::readSegments() {
goto eofError2;
}
+ // check for missing page information segment
+ if (!pageBitmap && ((segType >= 4 && segType <= 7) ||
+ (segType >= 20 && segType <= 43))) {
+ error(errSyntaxError, getPos(),
+ "First JBIG2 segment associated with a page must be a page information segment");
+ goto syntaxError;
+ }
+
// read the segment data
+ arithDecoder->resetByteCounter();
+ huffDecoder->resetByteCounter();
+ mmrDecoder->resetByteCounter();
+ byteCounter = 0;
switch (segType) {
case 0:
if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
@@ -1364,7 +1435,7 @@ void JBIG2Stream::readSegments() {
readExtensionSeg(segLength);
break;
default:
- error(getPos(), "Unknown segment type in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unknown segment type in JBIG2 stream");
for (i = 0; i < segLength; ++i) {
if ((c1 = curStr->getChar()) == EOF) {
goto eofError2;
@@ -1373,6 +1444,30 @@ void JBIG2Stream::readSegments() {
break;
}
+ // skip any unused data at the end of the segment
+ // (except for immediate generic region segments which have
+ // 0xffffffff = unspecified length)
+ if (!(segType == 38 && segLength == 0xffffffff)) {
+ byteCounter += arithDecoder->getByteCounter();
+ byteCounter += huffDecoder->getByteCounter();
+ byteCounter += mmrDecoder->getByteCounter();
+ // do a sanity check on byteCounter vs segLength -- if there is
+ // a problem, abort the decode
+ if (byteCounter > segLength ||
+ segLength - byteCounter > 65536) {
+ error(errSyntaxError, getPos(),
+ "Invalid segment length in JBIG2 stream");
+ gfree(refSegs);
+ break;
+ }
+ while (byteCounter < segLength) {
+ if (curStr->getChar() == EOF) {
+ break;
+ }
+ ++byteCounter;
+ }
+ }
+
gfree(refSegs);
}
@@ -1385,7 +1480,7 @@ void JBIG2Stream::readSegments() {
eofError2:
gfree(refSegs);
eofError1:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
@@ -1407,10 +1502,12 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
Guint symHeight, symWidth, totalWidth, x, symID;
int dh, dw, refAggNum, refDX, refDY, bmSize;
GBool ex;
- int run, cnt;
+ int run, cnt, c;
Guint i, j, k;
Guchar *p;
+ symWidths = NULL;
+
// symbol dictionary flags
if (!readUWord(&flags)) {
goto eofError;
@@ -1466,20 +1563,40 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
codeTables = new GList();
numInputSyms = 0;
for (i = 0; i < nRefSegs; ++i) {
- seg = findSegment(refSegs[i]);
- if (seg->getType() == jbig2SegSymbolDict) {
- numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
- } else if (seg->getType() == jbig2SegCodeTable) {
- codeTables->append(seg);
+ if ((seg = findSegment(refSegs[i]))) {
+ if (seg->getType() == jbig2SegSymbolDict) {
+ j = ((JBIG2SymbolDict *)seg)->getSize();
+ if (numInputSyms > UINT_MAX - j) {
+ error(errSyntaxError, getPos(),
+ "Too many input symbols in JBIG2 symbol dictionary");
+ delete codeTables;
+ goto eofError;
+ }
+ numInputSyms += j;
+ } else if (seg->getType() == jbig2SegCodeTable) {
+ codeTables->append(seg);
+ }
}
}
+ if (numInputSyms > UINT_MAX - numNewSyms) {
+ error(errSyntaxError, getPos(),
+ "Too many input symbols in JBIG2 symbol dictionary");
+ delete codeTables;
+ goto eofError;
+ }
// compute symbol code length
- symCodeLen = 0;
- i = 1;
- while (i < numInputSyms + numNewSyms) {
- ++symCodeLen;
- i <<= 1;
+ i = numInputSyms + numNewSyms;
+ if (i <= 1) {
+ symCodeLen = huff ? 1 : 0;
+ } else {
+ --i;
+ symCodeLen = 0;
+ // i = floor((numSyms-1) / 2^symCodeLen)
+ while (i > 0) {
+ ++symCodeLen;
+ i >>= 1;
+ }
}
// get the input symbol bitmaps
@@ -1491,11 +1608,12 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
k = 0;
inputSymbolDict = NULL;
for (i = 0; i < nRefSegs; ++i) {
- seg = findSegment(refSegs[i]);
- if (seg->getType() == jbig2SegSymbolDict) {
- inputSymbolDict = (JBIG2SymbolDict *)seg;
- for (j = 0; j < inputSymbolDict->getSize(); ++j) {
- bitmaps[k++] = inputSymbolDict->getBitmap(j);
+ if ((seg = findSegment(refSegs[i]))) {
+ if (seg->getType() == jbig2SegSymbolDict) {
+ inputSymbolDict = (JBIG2SymbolDict *)seg;
+ for (j = 0; j < inputSymbolDict->getSize(); ++j) {
+ bitmaps[k++] = inputSymbolDict->getBitmap(j);
+ }
}
}
}
@@ -1510,6 +1628,9 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
} else if (huffDH == 1) {
huffDHTable = huffTableE;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffDW == 0) {
@@ -1517,17 +1638,26 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
} else if (huffDW == 1) {
huffDWTable = huffTableC;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffBMSize == 0) {
huffBMSizeTable = huffTableA;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffBMSizeTable =
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffAggInst == 0) {
huffAggInstTable = huffTableA;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffAggInstTable =
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
@@ -1560,7 +1690,6 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
}
// allocate symbol widths storage
- symWidths = NULL;
if (huff && !refAgg) {
symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
}
@@ -1576,7 +1705,8 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
arithDecoder->decodeInt(&dh, iadhStats);
}
if (dh < 0 && (Guint)-dh >= symHeight) {
- error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
+ error(errSyntaxError, getPos(),
+ "Bad delta-height value in JBIG2 symbol dictionary");
goto syntaxError;
}
symHeight += dh;
@@ -1598,10 +1728,16 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
}
}
if (dw < 0 && (Guint)-dw >= symWidth) {
- error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
+ error(errSyntaxError, getPos(),
+ "Bad delta-height value in JBIG2 symbol dictionary");
goto syntaxError;
}
symWidth += dw;
+ if (i >= numNewSyms) {
+ error(errSyntaxError, getPos(),
+ "Too many symbols in JBIG2 symbol dictionary");
+ goto syntaxError;
+ }
// using a collective bitmap, so don't read a bitmap here
if (huff && !refAgg) {
@@ -1638,6 +1774,11 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
arithDecoder->decodeInt(&refDX, iardxStats);
arithDecoder->decodeInt(&refDY, iardyStats);
}
+ if (symID >= numInputSyms + i) {
+ error(errSyntaxError, getPos(),
+ "Invalid symbol ID in JBIG2 symbol dictionary");
+ goto syntaxError;
+ }
refBitmap = bitmaps[symID];
bitmaps[numInputSyms + i] =
readGenericRefinementRegion(symWidth, symHeight,
@@ -1675,7 +1816,11 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
bmSize = symHeight * ((totalWidth + 7) >> 3);
p = collBitmap->getDataPtr();
for (k = 0; k < (Guint)bmSize; ++k) {
- *p++ = curStr->getChar();
+ if ((c = curStr->getChar()) == EOF) {
+ break;
+ }
+ *p++ = (Guchar)c;
+ ++byteCounter;
}
} else {
collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
@@ -1704,6 +1849,13 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
} else {
arithDecoder->decodeInt(&run, iaexStats);
}
+ if (i + run > numInputSyms + numNewSyms ||
+ (ex && j + run > numExSyms)) {
+ error(errSyntaxError, getPos(),
+ "Too many exported symbols in JBIG2 symbol dictionary");
+ delete symbolDict;
+ goto syntaxError;
+ }
if (ex) {
for (cnt = 0; cnt < run; ++cnt) {
symbolDict->setBitmap(j++, bitmaps[i++]->copy());
@@ -1713,6 +1865,11 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
}
ex = !ex;
}
+ if (j != numExSyms) {
+ error(errSyntaxError, getPos(), "Too few symbols in JBIG2 symbol dictionary");
+ delete symbolDict;
+ goto syntaxError;
+ }
for (i = 0; i < numNewSyms; ++i) {
delete bitmaps[numInputSyms + i];
@@ -1735,6 +1892,10 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
return gTrue;
+ codeTableError:
+ error(errSyntaxError, getPos(), "Missing code table in JBIG2 symbol dictionary");
+ delete codeTables;
+
syntaxError:
for (i = 0; i < numNewSyms; ++i) {
if (bitmaps[numInputSyms + i]) {
@@ -1748,7 +1909,7 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
return gFalse;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
return gFalse;
}
@@ -1836,14 +1997,23 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
codeTables->append(seg);
}
} else {
- error(getPos(), "Invalid segment reference in JBIG2 text region");
+ error(errSyntaxError, getPos(),
+ "Invalid segment reference in JBIG2 text region");
+ delete codeTables;
+ return;
}
}
- symCodeLen = 0;
- i = 1;
- while (i < numSyms) {
- ++symCodeLen;
- i <<= 1;
+ i = numSyms;
+ if (i <= 1) {
+ symCodeLen = huff ? 1 : 0;
+ } else {
+ --i;
+ symCodeLen = 0;
+ // i = floor((numSyms-1) / 2^symCodeLen)
+ while (i > 0) {
+ ++symCodeLen;
+ i >>= 1;
+ }
}
// get the symbol bitmaps
@@ -1871,6 +2041,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffFS == 1) {
huffFSTable = huffTableG;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffDS == 0) {
@@ -1880,6 +2053,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffDS == 2) {
huffDSTable = huffTableJ;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffDT == 0) {
@@ -1889,6 +2065,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffDT == 2) {
huffDTTable = huffTableM;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffRDW == 0) {
@@ -1896,6 +2075,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffRDW == 1) {
huffRDWTable = huffTableO;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffRDH == 0) {
@@ -1903,6 +2085,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffRDH == 1) {
huffRDHTable = huffTableO;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffRDX == 0) {
@@ -1910,6 +2095,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffRDX == 1) {
huffRDXTable = huffTableO;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffRDY == 0) {
@@ -1917,11 +2105,17 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
} else if (huffRDY == 1) {
huffRDYTable = huffTableO;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
if (huffRSize == 0) {
huffRSizeTable = huffTableA;
} else {
+ if (i >= (Guint)codeTables->getLength()) {
+ goto codeTableError;
+ }
huffRSizeTable =
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
}
@@ -2016,8 +2210,15 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
return;
+ codeTableError:
+ error(errSyntaxError, getPos(), "Missing code table in JBIG2 text region");
+ gfree(codeTables);
+ delete syms;
+ return;
+
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
+ return;
}
JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
@@ -2088,7 +2289,9 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
s = sFirst;
// read the instances
- while (1) {
+ // (this loop test is here to avoid an infinite loop with damaged
+ // JBIG2 streams where the normal loop exit doesn't get triggered)
+ while (inst < numInstances) {
// T value
if (strips == 1) {
@@ -2113,7 +2316,8 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
}
if (symID >= (Guint)numSyms) {
- error(getPos(), "Invalid symbol number in JBIG2 text region");
+ error(errSyntaxError, getPos(),
+ "Invalid symbol number in JBIG2 text region");
} else {
// get the symbol bitmap
@@ -2269,7 +2473,7 @@ void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
@@ -2311,30 +2515,39 @@ void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
goto eofError;
}
if (w == 0 || h == 0 || w >= INT_MAX / h) {
- error(getPos(), "Bad bitmap size in JBIG2 halftone segment");
+ error(errSyntaxError, getPos(),
+ "Bad bitmap size in JBIG2 halftone segment");
return;
}
if (gridH == 0 || gridW >= INT_MAX / gridH) {
- error(getPos(), "Bad grid size in JBIG2 halftone segment");
+ error(errSyntaxError, getPos(), "Bad grid size in JBIG2 halftone segment");
return;
}
// get pattern dictionary
if (nRefSegs != 1) {
- error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ error(errSyntaxError, getPos(),
+ "Bad symbol dictionary reference in JBIG2 halftone segment");
return;
}
- seg = findSegment(refSegs[0]);
- if (seg->getType() != jbig2SegPatternDict) {
- error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ if (!(seg = findSegment(refSegs[0])) ||
+ seg->getType() != jbig2SegPatternDict) {
+ error(errSyntaxError, getPos(),
+ "Bad symbol dictionary reference in JBIG2 halftone segment");
return;
}
patternDict = (JBIG2PatternDict *)seg;
- bpp = 0;
- i = 1;
- while (i < patternDict->getSize()) {
- ++bpp;
- i <<= 1;
+ i = patternDict->getSize();
+ if (i <= 1) {
+ bpp = 0;
+ } else {
+ --i;
+ bpp = 0;
+ // i = floor((size-1) / 2^bpp)
+ while (i > 0) {
+ ++bpp;
+ i >>= 1;
+ }
}
patW = patternDict->getBitmap(0)->getWidth();
patH = patternDict->getBitmap(0)->getHeight();
@@ -2428,13 +2641,13 @@ void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
GBool lossless, Guint length) {
JBIG2Bitmap *bitmap;
- Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint w, h, x, y, segInfoFlags, extCombOp, rowCount;
Guint flags, mmr, templ, tpgdOn;
int atx[4], aty[4];
@@ -2483,7 +2696,7 @@ void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
// read the bitmap
bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
- NULL, atx, aty, mmr ? 0 : length - 18);
+ NULL, atx, aty, mmr ? length - 18 : 0);
// combine the region bitmap into the page bitmap
if (imm) {
@@ -2499,10 +2712,55 @@ void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
segments->append(bitmap);
}
+ // immediate generic segments can have an unspecified length, in
+ // which case, a row count is stored at the end of the segment
+ if (imm && length == 0xffffffff) {
+ readULong(&rowCount);
+ }
+
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+inline void JBIG2Stream::mmrAddPixels(int a1, int blackPixels,
+ int *codingLine, int *a0i, int w) {
+ if (a1 > codingLine[*a0i]) {
+ if (a1 > w) {
+ error(errSyntaxError, getPos(),
+ "JBIG2 MMR row is wrong length ({0:d})", a1);
+ a1 = w;
+ }
+ if ((*a0i & 1) ^ blackPixels) {
+ ++*a0i;
+ }
+ codingLine[*a0i] = a1;
+ }
+}
+
+inline void JBIG2Stream::mmrAddPixelsNeg(int a1, int blackPixels,
+ int *codingLine, int *a0i, int w) {
+ if (a1 > codingLine[*a0i]) {
+ if (a1 > w) {
+ error(errSyntaxError, getPos(),
+ "JBIG2 MMR row is wrong length ({0:d})", a1);
+ a1 = w;
+ }
+ if ((*a0i & 1) ^ blackPixels) {
+ ++*a0i;
+ }
+ codingLine[*a0i] = a1;
+ } else if (a1 < codingLine[*a0i]) {
+ if (a1 < 0) {
+ error(errSyntaxError, getPos(), "Invalid JBIG2 MMR code");
+ a1 = 0;
+ }
+ while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) {
+ --*a0i;
+ }
+ codingLine[*a0i] = a1;
+ }
}
JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
@@ -2513,11 +2771,16 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
JBIG2Bitmap *bitmap;
GBool ltp;
Guint ltpCX, cx, cx0, cx1, cx2;
- JBIG2BitmapPtr cxPtr0, cxPtr1;
- JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
int *refLine, *codingLine;
int code1, code2, code3;
- int x, y, a0, pix, i, refI, codingI;
+ Guchar *p0, *p1, *p2, *pp;
+ Guchar *atP0, *atP1, *atP2, *atP3;
+ Guint buf0, buf1, buf2;
+ Guint atBuf0, atBuf1, atBuf2, atBuf3;
+ int atShift0, atShift1, atShift2, atShift3;
+ Guchar mask;
+ int x, y, x0, x1, a0i, b1i, blackPixels, pix, i;
+
bitmap = new JBIG2Bitmap(0, w, h);
bitmap->clearToZero();
@@ -2527,9 +2790,18 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
if (mmr) {
mmrDecoder->reset();
+ if (w > INT_MAX - 2) {
+ error(errSyntaxError, getPos(), "Bad width in JBIG2 generic bitmap");
+ // force a call to gmalloc(-1), which will throw an exception
+ w = -3;
+ }
+ // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
+ // ---> max codingLine size = w + 1
+ // refLine has one extra guard entry at the end
+ // ---> max refLine size = w + 2
+ codingLine = (int *)gmallocn(w + 1, sizeof(int));
refLine = (int *)gmallocn(w + 2, sizeof(int));
- codingLine = (int *)gmallocn(w + 2, sizeof(int));
- codingLine[0] = codingLine[1] = w;
+ codingLine[0] = w;
for (y = 0; y < h; ++y) {
@@ -2537,128 +2809,158 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
for (i = 0; codingLine[i] < w; ++i) {
refLine[i] = codingLine[i];
}
- refLine[i] = refLine[i + 1] = w;
+ refLine[i++] = w;
+ refLine[i] = w;
// decode a line
- refI = 0; // b1 = refLine[refI]
- codingI = 0; // a1 = codingLine[codingI]
- a0 = 0;
- do {
+ codingLine[0] = 0;
+ a0i = 0;
+ b1i = 0;
+ blackPixels = 0;
+ // invariant:
+ // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w
+ // exception at left edge:
+ // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
+ // exception at right edge:
+ // refLine[b1i] = refLine[b1i+1] = w is possible
+ while (codingLine[a0i] < w) {
code1 = mmrDecoder->get2DCode();
switch (code1) {
case twoDimPass:
- if (refLine[refI] < w) {
- a0 = refLine[refI + 1];
- refI += 2;
- }
- break;
+ mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w);
+ if (refLine[b1i + 1] < w) {
+ b1i += 2;
+ }
+ break;
case twoDimHoriz:
- if (codingI & 1) {
- code1 = 0;
- do {
- code1 += code3 = mmrDecoder->getBlackCode();
- } while (code3 >= 64);
- code2 = 0;
- do {
- code2 += code3 = mmrDecoder->getWhiteCode();
- } while (code3 >= 64);
- } else {
- code1 = 0;
- do {
- code1 += code3 = mmrDecoder->getWhiteCode();
- } while (code3 >= 64);
- code2 = 0;
- do {
- code2 += code3 = mmrDecoder->getBlackCode();
- } while (code3 >= 64);
- }
- if (code1 > 0 || code2 > 0) {
- a0 = codingLine[codingI++] = a0 + code1;
- a0 = codingLine[codingI++] = a0 + code2;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVert0:
- a0 = codingLine[codingI++] = refLine[refI];
- if (refLine[refI] < w) {
- ++refI;
- }
- break;
- case twoDimVertR1:
- a0 = codingLine[codingI++] = refLine[refI] + 1;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVertR2:
- a0 = codingLine[codingI++] = refLine[refI] + 2;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
+ code1 = code2 = 0;
+ if (blackPixels) {
+ do {
+ code1 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ } else {
+ do {
+ code1 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ }
+ mmrAddPixels(codingLine[a0i] + code1, blackPixels,
+ codingLine, &a0i, w);
+ if (codingLine[a0i] < w) {
+ mmrAddPixels(codingLine[a0i] + code2, blackPixels ^ 1,
+ codingLine, &a0i, w);
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ break;
case twoDimVertR3:
- a0 = codingLine[codingI++] = refLine[refI] + 3;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVertL1:
- a0 = codingLine[codingI++] = refLine[refI] - 1;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
- case twoDimVertL2:
- a0 = codingLine[codingI++] = refLine[refI] - 2;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
+ mmrAddPixels(refLine[b1i] + 3, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case twoDimVertR2:
+ mmrAddPixels(refLine[b1i] + 2, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case twoDimVertR1:
+ mmrAddPixels(refLine[b1i] + 1, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case twoDimVert0:
+ mmrAddPixels(refLine[b1i], blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
case twoDimVertL3:
- a0 = codingLine[codingI++] = refLine[refI] - 3;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
+ mmrAddPixelsNeg(refLine[b1i] - 3, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case twoDimVertL2:
+ mmrAddPixelsNeg(refLine[b1i] - 2, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case twoDimVertL1:
+ mmrAddPixelsNeg(refLine[b1i] - 1, blackPixels, codingLine, &a0i, w);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < w) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
+ b1i += 2;
+ }
+ }
+ break;
+ case EOF:
+ mmrAddPixels(w, 0, codingLine, &a0i, w);
+ break;
default:
- error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
+ error(errSyntaxError, getPos(),
+ "Illegal code in JBIG2 MMR bitmap data");
+ mmrAddPixels(w, 0, codingLine, &a0i, w);
break;
}
- } while (a0 < w);
- codingLine[codingI++] = w;
+ }
// convert the run lengths to a bitmap line
i = 0;
- while (codingLine[i] < w) {
+ while (1) {
for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
bitmap->setPixel(x, y);
}
+ if (codingLine[i+1] >= w || codingLine[i+2] >= w) {
+ break;
+ }
i += 2;
}
}
@@ -2667,7 +2969,8 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
mmrDecoder->skipTo(mmrDataLength);
} else {
if (mmrDecoder->get24Bits() != 0x001001) {
- error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
+ error(errSyntaxError, getPos(),
+ "Missing EOFB in JBIG2 MMR bitmap data");
}
}
@@ -2706,7 +3009,9 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
ltp = !ltp;
}
if (ltp) {
- bitmap->duplicateRow(y, y-1);
+ if (y > 0) {
+ bitmap->duplicateRow(y, y-1);
+ }
continue;
}
}
@@ -2715,145 +3020,497 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
case 0:
// set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
- bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
- bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
- bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
- (bitmap->nextPixel(&atPtr0) << 3) |
- (bitmap->nextPixel(&atPtr1) << 2) |
- (bitmap->nextPixel(&atPtr2) << 1) |
- bitmap->nextPixel(&atPtr3);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
+ p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
+ buf2 = *p2++ << 8;
+ if (y >= 1) {
+ p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
+ buf1 = *p1++ << 8;
+ if (y >= 2) {
+ p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
+ buf0 = *p0++ << 8;
+ } else {
+ p0 = NULL;
+ buf0 = 0;
}
+ } else {
+ p1 = p0 = NULL;
+ buf1 = buf0 = 0;
+ }
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
+ if (atx[0] >= -8 && atx[0] <= 8 &&
+ atx[1] >= -8 && atx[1] <= 8 &&
+ atx[2] >= -8 && atx[2] <= 8 &&
+ atx[3] >= -8 && atx[3] <= 8) {
+ // set up the adaptive context
+ if (y + aty[0] >= 0) {
+ atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
+ atBuf0 = *atP0++ << 8;
+ } else {
+ atP0 = NULL;
+ atBuf0 = 0;
+ }
+ atShift0 = 15 - atx[0];
+ if (y + aty[1] >= 0) {
+ atP1 = bitmap->getDataPtr() + (y + aty[1]) * bitmap->getLineSize();
+ atBuf1 = *atP1++ << 8;
+ } else {
+ atP1 = NULL;
+ atBuf1 = 0;
+ }
+ atShift1 = 15 - atx[1];
+ if (y + aty[2] >= 0) {
+ atP2 = bitmap->getDataPtr() + (y + aty[2]) * bitmap->getLineSize();
+ atBuf2 = *atP2++ << 8;
+ } else {
+ atP2 = NULL;
+ atBuf2 = 0;
+ }
+ atShift2 = 15 - atx[2];
+ if (y + aty[3] >= 0) {
+ atP3 = bitmap->getDataPtr() + (y + aty[3]) * bitmap->getLineSize();
+ atBuf3 = *atP3++ << 8;
+ } else {
+ atP3 = NULL;
+ atBuf3 = 0;
+ }
+ atShift3 = 15 - atx[3];
+
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ if (atP0) {
+ atBuf0 |= *atP0++;
+ }
+ if (atP1) {
+ atBuf1 |= *atP1++;
+ }
+ if (atP2) {
+ atBuf2 |= *atP2++;
+ }
+ if (atP3) {
+ atBuf3 |= *atP3++;
+ }
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 14) & 0x07;
+ cx1 = (buf1 >> 13) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x0f;
+ cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
+ (((atBuf0 >> atShift0) & 1) << 3) |
+ (((atBuf1 >> atShift1) & 1) << 2) |
+ (((atBuf2 >> atShift2) & 1) << 1) |
+ ((atBuf3 >> atShift3) & 1);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ if (aty[0] == 0) {
+ atBuf0 |= 0x8000;
+ }
+ if (aty[1] == 0) {
+ atBuf1 |= 0x8000;
+ }
+ if (aty[2] == 0) {
+ atBuf2 |= 0x8000;
+ }
+ if (aty[3] == 0) {
+ atBuf3 |= 0x8000;
+ }
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ atBuf0 <<= 1;
+ atBuf1 <<= 1;
+ atBuf2 <<= 1;
+ atBuf3 <<= 1;
+ }
+ }
+
+ } else {
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 14) & 0x07;
+ cx1 = (buf1 >> 13) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x0f;
+ cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
+ (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
+ (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
+ (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
+ bitmap->getPixel(x + atx[3], y + aty[3]);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ }
+ }
}
break;
case 1:
// set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
+ p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
+ buf2 = *p2++ << 8;
+ if (y >= 1) {
+ p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
+ buf1 = *p1++ << 8;
+ if (y >= 2) {
+ p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
+ buf0 = *p0++ << 8;
+ } else {
+ p0 = NULL;
+ buf0 = 0;
+ }
+ } else {
+ p1 = p0 = NULL;
+ buf1 = buf0 = 0;
+ }
+
+ if (atx[0] >= -8 && atx[0] <= 8) {
+ // set up the adaptive context
+ if (y + aty[0] >= 0) {
+ atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
+ atBuf0 = *atP0++ << 8;
+ } else {
+ atP0 = NULL;
+ atBuf0 = 0;
+ }
+ atShift0 = 15 - atx[0];
+
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ if (atP0) {
+ atBuf0 |= *atP0++;
+ }
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 13) & 0x0f;
+ cx1 = (buf1 >> 13) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x07;
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ ((atBuf0 >> atShift0) & 1);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ if (aty[0] == 0) {
+ atBuf0 |= 0x8000;
+ }
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ atBuf0 <<= 1;
+ }
}
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x07;
+ } else {
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 13) & 0x0f;
+ cx1 = (buf1 >> 13) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x07;
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ bitmap->getPixel(x + atx[0], y + aty[0]);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ }
+ }
}
break;
case 2:
// set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
+ p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
+ buf2 = *p2++ << 8;
+ if (y >= 1) {
+ p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
+ buf1 = *p1++ << 8;
+ if (y >= 2) {
+ p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
+ buf0 = *p0++ << 8;
+ } else {
+ p0 = NULL;
+ buf0 = 0;
+ }
+ } else {
+ p1 = p0 = NULL;
+ buf1 = buf0 = 0;
+ }
+
+ if (atx[0] >= -8 && atx[0] <= 8) {
+ // set up the adaptive context
+ if (y + aty[0] >= 0) {
+ atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
+ atBuf0 = *atP0++ << 8;
+ } else {
+ atP0 = NULL;
+ atBuf0 = 0;
+ }
+ atShift0 = 15 - atx[0];
+
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ if (atP0) {
+ atBuf0 |= *atP0++;
+ }
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 14) & 0x07;
+ cx1 = (buf1 >> 14) & 0x0f;
+ cx2 = (buf2 >> 16) & 0x03;
+ cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
+ ((atBuf0 >> atShift0) & 1);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ if (aty[0] == 0) {
+ atBuf0 |= 0x8000;
+ }
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ atBuf0 <<= 1;
+ }
}
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
- cx2 = ((cx2 << 1) | pix) & 0x03;
+ } else {
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p0) {
+ buf0 |= *p0++;
+ }
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx0 = (buf0 >> 14) & 0x07;
+ cx1 = (buf1 >> 14) & 0x0f;
+ cx2 = (buf2 >> 16) & 0x03;
+ cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
+ bitmap->getPixel(x + atx[0], y + aty[0]);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ }
+ }
+
+ // update the context
+ buf0 <<= 1;
+ buf1 <<= 1;
+ buf2 <<= 1;
+ }
+ }
}
break;
case 3:
// set up the context
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx1 << 5) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
+ p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
+ buf2 = *p2++ << 8;
+ if (y >= 1) {
+ p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
+ buf1 = *p1++ << 8;
+ } else {
+ p1 = NULL;
+ buf1 = 0;
+ }
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
+ if (atx[0] >= -8 && atx[0] <= 8) {
+ // set up the adaptive context
+ if (y + aty[0] >= 0) {
+ atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
+ atBuf0 = *atP0++ << 8;
+ } else {
+ atP0 = NULL;
+ atBuf0 = 0;
+ }
+ atShift0 = 15 - atx[0];
+
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ if (atP0) {
+ atBuf0 |= *atP0++;
+ }
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx1 = (buf1 >> 14) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x0f;
+ cx = (cx1 << 5) | (cx2 << 1) |
+ ((atBuf0 >> atShift0) & 1);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ if (aty[0] == 0) {
+ atBuf0 |= 0x8000;
+ }
+ }
+ }
+
+ // update the context
+ buf1 <<= 1;
+ buf2 <<= 1;
+ atBuf0 <<= 1;
+ }
}
- // update the context
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
+ } else {
+ // decode the row
+ for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
+ if (x0 + 8 < w) {
+ if (p1) {
+ buf1 |= *p1++;
+ }
+ buf2 |= *p2++;
+ }
+ for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
+
+ // build the context
+ cx1 = (buf1 >> 14) & 0x1f;
+ cx2 = (buf2 >> 16) & 0x0f;
+ cx = (cx1 << 5) | (cx2 << 1) |
+ bitmap->getPixel(x + atx[0], y + aty[0]);
+
+ // check for a skipped pixel
+ if (!(useSkip && skip->getPixel(x, y))) {
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ *pp |= mask;
+ buf2 |= 0x8000;
+ }
+ }
+
+ // update the context
+ buf1 <<= 1;
+ buf2 <<= 1;
+ }
+ }
}
break;
}
@@ -2905,13 +3562,15 @@ void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
// get referenced bitmap
if (nRefSegs > 1) {
- error(getPos(), "Bad reference in JBIG2 generic refinement segment");
+ error(errSyntaxError, getPos(),
+ "Bad reference in JBIG2 generic refinement segment");
return;
}
if (nRefSegs == 1) {
- seg = findSegment(refSegs[0]);
- if (seg->getType() != jbig2SegBitmap) {
- error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
+ if (!(seg = findSegment(refSegs[0])) ||
+ seg->getType() != jbig2SegBitmap) {
+ error(errSyntaxError, getPos(),
+ "Bad bitmap reference in JBIG2 generic refinement segment");
return;
}
refBitmap = (JBIG2Bitmap *)seg;
@@ -2948,7 +3607,7 @@ void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
@@ -3004,6 +3663,10 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ } else {
+ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
+ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
+ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
}
for (x = 0; x < w; ++x) {
@@ -3075,6 +3738,10 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ } else {
+ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
+ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
+ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
}
for (x = 0; x < w; ++x) {
@@ -3150,7 +3817,7 @@ void JBIG2Stream::readPageInfoSeg(Guint length) {
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
void JBIG2Stream::readEndOfStripeSeg(Guint length) {
@@ -3158,7 +3825,10 @@ void JBIG2Stream::readEndOfStripeSeg(Guint length) {
// skip the segment
for (i = 0; i < length; ++i) {
- curStr->getChar();
+ if (curStr->getChar() == EOF) {
+ break;
+ }
+ ++byteCounter;
}
}
@@ -3167,7 +3837,10 @@ void JBIG2Stream::readProfilesSeg(Guint length) {
// skip the segment
for (i = 0; i < length; ++i) {
- curStr->getChar();
+ if (curStr->getChar() == EOF) {
+ break;
+ }
+ ++byteCounter;
}
}
@@ -3232,7 +3905,7 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
return;
eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
}
void JBIG2Stream::readExtensionSeg(Guint length) {
@@ -3240,7 +3913,10 @@ void JBIG2Stream::readExtensionSeg(Guint length) {
// skip the segment
for (i = 0; i < length; ++i) {
- curStr->getChar();
+ if (curStr->getChar() == EOF) {
+ break;
+ }
+ ++byteCounter;
}
}
@@ -3355,6 +4031,7 @@ GBool JBIG2Stream::readUByte(Guint *x) {
if ((c0 = curStr->getChar()) == EOF) {
return gFalse;
}
+ ++byteCounter;
*x = (Guint)c0;
return gTrue;
}
@@ -3365,6 +4042,7 @@ GBool JBIG2Stream::readByte(int *x) {
if ((c0 = curStr->getChar()) == EOF) {
return gFalse;
}
+ ++byteCounter;
*x = c0;
if (c0 & 0x80) {
*x |= -1 - 0xff;
@@ -3379,6 +4057,7 @@ GBool JBIG2Stream::readUWord(Guint *x) {
(c1 = curStr->getChar()) == EOF) {
return gFalse;
}
+ byteCounter += 2;
*x = (Guint)((c0 << 8) | c1);
return gTrue;
}
@@ -3392,6 +4071,7 @@ GBool JBIG2Stream::readULong(Guint *x) {
(c3 = curStr->getChar()) == EOF) {
return gFalse;
}
+ byteCounter += 4;
*x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
return gTrue;
}
@@ -3405,6 +4085,7 @@ GBool JBIG2Stream::readLong(int *x) {
(c3 = curStr->getChar()) == EOF) {
return gFalse;
}
+ byteCounter += 4;
*x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
if (c0 & 0x80) {
*x |= -1 - (int)0xffffffff;
diff --git a/xpdf/JBIG2Stream.h b/xpdf/JBIG2Stream.h
index 210d927..660f582 100644
--- a/xpdf/JBIG2Stream.h
+++ b/xpdf/JBIG2Stream.h
@@ -40,7 +40,8 @@ public:
virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual int getBlock(char *blk, int size);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -78,6 +79,10 @@ private:
Guint *refSegs, Guint nRefSegs);
void readGenericRegionSeg(Guint segNum, GBool imm,
GBool lossless, Guint length);
+ void mmrAddPixels(int a1, int blackPixels,
+ int *codingLine, int *a0i, int w);
+ void mmrAddPixelsNeg(int a1, int blackPixels,
+ int *codingLine, int *a0i, int w);
JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h,
int templ, GBool tpgdOn,
GBool useSkip, JBIG2Bitmap *skip,
@@ -120,6 +125,7 @@ private:
Stream *curStr;
Guchar *dataPtr;
Guchar *dataEnd;
+ Guint byteCounter;
JArithmeticDecoder *arithDecoder;
JArithmeticDecoderStats *genericRegionStats;
diff --git a/xpdf/JPXStream.cc b/xpdf/JPXStream.cc
index 7107854..98dcfef 100644
--- a/xpdf/JPXStream.cc
+++ b/xpdf/JPXStream.cc
@@ -26,16 +26,11 @@
// - support for palettes, channel maps, etc.
// - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
// - can we assume that QCC segments must come after the QCD segment?
-// - skip EPH markers (readTilePartData)
// - handle tilePartToEOC in readTilePartData
-// - deal with multiple codeword segments (readTilePartData,
-// readCodeBlockData)
// - progression orders 2, 3, and 4
// - in coefficient decoding (readCodeBlockData):
-// - termination pattern: terminate after every coding pass
-// - error resilience segmentation symbol
// - selective arithmetic coding bypass
-// - vertically causal context formation
+// (this also affects reading the cb->dataLen array)
// - coeffs longer than 31 bits (should just ignore the extra bits?)
// - handle boxes larger than 2^32 bytes
// - the fixed-point arithmetic won't handle 16-bit pixels
@@ -233,6 +228,8 @@ JPXCover jpxCover(150);
JPXStream::JPXStream(Stream *strA):
FilterStream(strA)
{
+ bufStr = new BufStream(str, 2);
+
nComps = 0;
bpc = NULL;
width = height = 0;
@@ -250,11 +247,11 @@ JPXStream::JPXStream(Stream *strA):
JPXStream::~JPXStream() {
close();
- delete str;
+ delete bufStr;
}
void JPXStream::reset() {
- str->reset();
+ bufStr->reset();
if (readBoxes()) {
curY = img.yOffset;
} else {
@@ -318,7 +315,8 @@ void JPXStream::close() {
if (subband->cbs) {
for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
cb = &subband->cbs[k];
- gfree(cb->coeffs);
+ gfree(cb->dataLen);
+ gfree(cb->touched);
if (cb->arithDecoder) {
delete cb->arithDecoder;
}
@@ -344,7 +342,7 @@ void JPXStream::close() {
gfree(img.tiles);
img.tiles = NULL;
}
- FilterStream::close();
+ bufStr->close();
}
int JPXStream::getChar() {
@@ -413,7 +411,8 @@ void JPXStream::fillReadBuf() {
if (pix >= 0 && pix < palette.nEntries) {
pix = palette.c[pix * palette.nComps + curComp];
} else {
- pix =
+ pix = 0;
+ }
pixBits = palette.bpc[curComp];
}
if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
@@ -422,6 +421,10 @@ void JPXStream::fillReadBuf() {
if (++curX == img.xSize) {
curX = img.xOffset;
++curY;
+ if (pixBits < 8) {
+ pix <<= 8 - pixBits;
+ pixBits = 8;
+ }
}
}
if (pixBits == 8) {
@@ -433,7 +436,7 @@ void JPXStream::fillReadBuf() {
} while (readBufLen < 8);
}
-GString *JPXStream::getPSFilter(int psLevel, char *indent) {
+GString *JPXStream::getPSFilter(int psLevel, const char *indent) {
return NULL;
}
@@ -451,8 +454,8 @@ void JPXStream::getImageParams(int *bitsPerComponent,
csPrec = 0; // make gcc happy
haveBPC = haveCSMode = gFalse;
- str->reset();
- if (str->lookChar() == 0xff) {
+ bufStr->reset();
+ if (bufStr->lookChar() == 0xff) {
getImageParams2(bitsPerComponent, csMode);
} else {
while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
@@ -496,12 +499,12 @@ void JPXStream::getImageParams(int *bitsPerComponent,
haveCSMode = gTrue;
}
for (i = 0; i < dataLen - 7; ++i) {
- str->getChar();
+ bufStr->getChar();
}
}
} else {
for (i = 0; i < dataLen - 3; ++i) {
- str->getChar();
+ bufStr->getChar();
}
}
}
@@ -514,12 +517,12 @@ void JPXStream::getImageParams(int *bitsPerComponent,
} else {
cover(4);
for (i = 0; i < dataLen; ++i) {
- str->getChar();
+ bufStr->getChar();
}
}
}
}
- str->close();
+ bufStr->close();
}
// Get image parameters from the codestream.
@@ -557,7 +560,7 @@ void JPXStream::getImageParams2(int *bitsPerComponent,
cover(6);
if (segLen > 2) {
for (i = 0; i < segLen - 2; ++i) {
- str->getChar();
+ bufStr->getChar();
}
}
}
@@ -574,10 +577,13 @@ GBool JPXStream::readBoxes() {
// check for a naked JPEG 2000 codestream (without the JP2/JPX
// wrapper) -- this appears to be a violation of the PDF spec, but
// Acrobat allows it
- if (str->lookChar() == 0xff) {
+ if (bufStr->lookChar() == 0xff) {
cover(7);
- error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
- readCodestream(0);
+ error(errSyntaxWarning, getPos(),
+ "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
+ if (!readCodestream(0)) {
+ return gFalse;
+ }
nComps = img.nComps;
bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
for (i = 0; i < nComps; ++i) {
@@ -607,11 +613,12 @@ GBool JPXStream::readBoxes() {
!readUByte(&compression) ||
!readUByte(&unknownColorspace) ||
!readUByte(&ipr)) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
if (compression != 7) {
- error(getPos(), "Unknown compression type in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Unknown compression type in JPX stream");
return gFalse;
}
bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
@@ -623,16 +630,18 @@ GBool JPXStream::readBoxes() {
case 0x62706363: // bits per component
cover(10);
if (!haveImgHdr) {
- error(getPos(), "Found bits per component box before image header box in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Found bits per component box before image header box in JPX stream");
return gFalse;
}
if (dataLen != nComps) {
- error(getPos(), "Invalid bits per component box in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Invalid bits per component box in JPX stream");
return gFalse;
}
for (i = 0; i < nComps; ++i) {
if (!readUByte(&bpc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
}
@@ -647,7 +656,7 @@ GBool JPXStream::readBoxes() {
cover(12);
if (!readUWord(&palette.nEntries) ||
!readUByte(&palette.nComps)) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint));
@@ -655,7 +664,7 @@ GBool JPXStream::readBoxes() {
(int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int));
for (i = 0; i < palette.nComps; ++i) {
if (!readUByte(&palette.bpc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
++palette.bpc[i];
@@ -665,7 +674,7 @@ GBool JPXStream::readBoxes() {
if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
(palette.bpc[j] & 0x80) ? gTrue : gFalse,
&palette.c[i * palette.nComps + j])) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
}
@@ -682,7 +691,7 @@ GBool JPXStream::readBoxes() {
if (!readUWord(&compMap.comp[i]) ||
!readUByte(&compMap.type[i]) ||
!readUByte(&compMap.pComp[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
}
@@ -691,7 +700,7 @@ GBool JPXStream::readBoxes() {
case 0x63646566: // channel definition
cover(14);
if (!readUWord(&channelDefn.nChannels)) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
channelDefn.idx =
@@ -704,7 +713,7 @@ GBool JPXStream::readBoxes() {
if (!readUWord(&channelDefn.idx[i]) ||
!readUWord(&channelDefn.type[i]) ||
!readUWord(&channelDefn.assoc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
}
@@ -713,10 +722,12 @@ GBool JPXStream::readBoxes() {
case 0x6A703263: // contiguous codestream
cover(15);
if (!bpc) {
- error(getPos(), "JPX stream is missing the image header box");
+ error(errSyntaxError, getPos(),
+ "JPX stream is missing the image header box");
}
if (!haveCS) {
- error(getPos(), "JPX stream has no supported color spec");
+ error(errSyntaxError, getPos(),
+ "JPX stream has no supported color spec");
}
if (!readCodestream(dataLen)) {
return gFalse;
@@ -725,8 +736,8 @@ GBool JPXStream::readBoxes() {
default:
cover(16);
for (i = 0; i < dataLen; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Unexpected EOF in JPX stream");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
return gFalse;
}
}
@@ -842,7 +853,7 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) {
case 4: // vendor color (JPX)
cover(18);
for (i = 0; i < dataLen - 3; ++i) {
- if (str->getChar() == EOF) {
+ if (bufStr->getChar() == EOF) {
goto err;
}
}
@@ -857,7 +868,7 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) {
return gTrue;
err:
- error(getPos(), "Error in JPX color spec");
+ error(errSyntaxError, getPos(), "Error in JPX color spec");
return gFalse;
}
@@ -873,7 +884,7 @@ GBool JPXStream::readCodestream(Guint len) {
haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
do {
if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX codestream");
+ error(errSyntaxError, getPos(), "Error in JPX codestream");
return gFalse;
}
switch (segType) {
@@ -883,6 +894,11 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x51: // SIZ - image and tile size
cover(20);
+ if (haveSIZ) {
+ error(errSyntaxError, getPos(),
+ "Duplicate SIZ marker segment in JPX stream");
+ return gFalse;
+ }
if (!readUWord(&capabilities) ||
!readULong(&img.xSize) ||
!readULong(&img.ySize) ||
@@ -893,11 +909,22 @@ GBool JPXStream::readCodestream(Guint len) {
!readULong(&img.xTileOffset) ||
!readULong(&img.yTileOffset) ||
!readUWord(&img.nComps)) {
- error(getPos(), "Error in JPX SIZ marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
return gFalse;
}
if (haveImgHdr && img.nComps != nComps) {
- error(getPos(), "Different number of components in JPX SIZ marker segment");
+ error(errSyntaxError, getPos(),
+ "Different number of components in JPX SIZ marker segment");
+ return gFalse;
+ }
+ if (img.xSize == 0 || img.ySize == 0 ||
+ img.xOffset >= img.xSize || img.yOffset >= img.ySize ||
+ img.xTileSize == 0 || img.yTileSize == 0 ||
+ img.xTileOffset > img.xOffset ||
+ img.yTileOffset > img.yOffset ||
+ img.xTileSize + img.xTileOffset <= img.xOffset ||
+ img.yTileSize + img.yTileOffset <= img.yOffset) {
+ error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
return gFalse;
}
img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
@@ -907,12 +934,14 @@ GBool JPXStream::readCodestream(Guint len) {
// 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");
+ error(errSyntaxError, getPos(),
+ "Bad tile count in JPX SIZ marker segment");
return gFalse;
}
img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles,
sizeof(JPXTile));
for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ img.tiles[i].init = gFalse;
img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
sizeof(JPXTileComp));
for (comp = 0; comp < img.nComps; ++comp) {
@@ -926,7 +955,12 @@ GBool JPXStream::readCodestream(Guint len) {
if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
!readUByte(&img.tiles[0].tileComps[comp].hSep) ||
!readUByte(&img.tiles[0].tileComps[comp].vSep)) {
- error(getPos(), "Error in JPX SIZ marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
+ return gFalse;
+ }
+ if (img.tiles[0].tileComps[comp].hSep == 0 ||
+ img.tiles[0].tileComps[comp].vSep == 0) {
+ error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
return gFalse;
}
img.tiles[0].tileComps[comp].sgned =
@@ -941,6 +975,11 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x52: // COD - coding style default
cover(21);
+ if (!haveSIZ) {
+ error(errSyntaxError, getPos(),
+ "JPX COD marker segment before SIZ segment");
+ return gFalse;
+ }
if (!readUByte(&img.tiles[0].tileComps[0].style) ||
!readUByte(&img.tiles[0].progOrder) ||
!readUWord(&img.tiles[0].nLayers) ||
@@ -950,7 +989,13 @@ GBool JPXStream::readCodestream(Guint len) {
!readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
!readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
!readUByte(&img.tiles[0].tileComps[0].transform)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ if (img.tiles[0].tileComps[0].nDecompLevels > 32 ||
+ img.tiles[0].tileComps[0].codeBlockW > 8 ||
+ img.tiles[0].tileComps[0].codeBlockH > 8) {
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[0].tileComps[0].codeBlockW += 2;
@@ -989,7 +1034,7 @@ GBool JPXStream::readCodestream(Guint len) {
if (img.tiles[0].tileComps[0].style & 0x01) {
cover(91);
if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
@@ -1018,7 +1063,8 @@ GBool JPXStream::readCodestream(Guint len) {
case 0x53: // COC - coding style component
cover(22);
if (!haveCOD) {
- error(getPos(), "JPX COC marker segment before COD segment");
+ error(errSyntaxError, getPos(),
+ "JPX COC marker segment before COD segment");
return gFalse;
}
if ((img.nComps > 256 && !readUWord(&comp)) ||
@@ -1030,7 +1076,13 @@ GBool JPXStream::readCodestream(Guint len) {
!readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
!readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
!readUByte(&img.tiles[0].tileComps[comp].transform)) {
- error(getPos(), "Error in JPX COC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
+ return gFalse;
+ }
+ if (img.tiles[0].tileComps[comp].nDecompLevels > 32 ||
+ img.tiles[0].tileComps[comp].codeBlockW > 8 ||
+ img.tiles[0].tileComps[comp].codeBlockH > 8) {
+ error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
return gFalse;
}
img.tiles[0].tileComps[comp].style =
@@ -1064,7 +1116,7 @@ GBool JPXStream::readCodestream(Guint len) {
for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
if (img.tiles[0].tileComps[comp].style & 0x01) {
if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
@@ -1087,11 +1139,20 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x5c: // QCD - quantization default
cover(23);
+ if (!haveSIZ) {
+ error(errSyntaxError, getPos(),
+ "JPX QCD marker segment before SIZ segment");
+ return gFalse;
+ }
if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
+ if (segLen <= 3) {
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
img.tiles[0].tileComps[0].quantSteps =
(Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
@@ -1099,7 +1160,7 @@ GBool JPXStream::readCodestream(Guint len) {
sizeof(Guint));
for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
@@ -1110,10 +1171,14 @@ GBool JPXStream::readCodestream(Guint len) {
img.tiles[0].tileComps[0].nQuantSteps,
sizeof(Guint));
if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
} else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
+ if (segLen < 5) {
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
img.tiles[0].tileComps[0].quantSteps =
(Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
@@ -1121,12 +1186,12 @@ GBool JPXStream::readCodestream(Guint len) {
sizeof(Guint));
for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
} else {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
@@ -1152,17 +1217,22 @@ GBool JPXStream::readCodestream(Guint len) {
case 0x5d: // QCC - quantization component
cover(24);
if (!haveQCD) {
- error(getPos(), "JPX QCC marker segment before QCD segment");
+ error(errSyntaxError, getPos(),
+ "JPX QCC marker segment before QCD segment");
return gFalse;
}
if ((img.nComps > 256 && !readUWord(&comp)) ||
(img.nComps <= 256 && !readUByte(&comp)) ||
comp >= img.nComps ||
!readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
+ if (segLen <= (img.nComps > 256 ? 5U : 4U)) {
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
img.tiles[0].tileComps[comp].nQuantSteps =
segLen - (img.nComps > 256 ? 5 : 4);
img.tiles[0].tileComps[comp].quantSteps =
@@ -1171,7 +1241,7 @@ GBool JPXStream::readCodestream(Guint len) {
sizeof(Guint));
for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
}
@@ -1182,10 +1252,14 @@ GBool JPXStream::readCodestream(Guint len) {
img.tiles[0].tileComps[comp].nQuantSteps,
sizeof(Guint));
if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
} else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
+ if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) {
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
img.tiles[0].tileComps[comp].nQuantSteps =
(segLen - (img.nComps > 256 ? 5 : 4)) / 2;
img.tiles[0].tileComps[comp].quantSteps =
@@ -1194,12 +1268,12 @@ GBool JPXStream::readCodestream(Guint len) {
sizeof(Guint));
for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
} else {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
@@ -1220,10 +1294,10 @@ GBool JPXStream::readCodestream(Guint len) {
case 0x5e: // RGN - region of interest
cover(25);
#if 1 //~ ROI is unimplemented
- fprintf(stderr, "RGN\n");
+ error(errUnimplemented, -1, "got a JPX RGN segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
return gFalse;
}
}
@@ -1233,7 +1307,7 @@ GBool JPXStream::readCodestream(Guint len) {
comp >= img.nComps ||
!readUByte(&compInfo[comp].defROI.style) ||
!readUByte(&compInfo[comp].defROI.shift)) {
- error(getPos(), "Error in JPX RGN marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
return gFalse;
}
#endif
@@ -1241,10 +1315,10 @@ GBool JPXStream::readCodestream(Guint len) {
case 0x5f: // POC - progression order change
cover(26);
#if 1 //~ progression order changes are unimplemented
- fprintf(stderr, "POC\n");
+ error(errUnimplemented, -1, "got a JPX POC segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
return gFalse;
}
}
@@ -1260,7 +1334,7 @@ GBool JPXStream::readCodestream(Guint len) {
!(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
!(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
!readUByte(&progs[i].progOrder)) {
- error(getPos(), "Error in JPX POC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
return gFalse;
}
}
@@ -1269,10 +1343,10 @@ GBool JPXStream::readCodestream(Guint len) {
case 0x60: // PPM - packed packet headers, main header
cover(27);
#if 1 //~ packed packet headers are unimplemented
- fprintf(stderr, "PPM\n");
+ error(errUnimplemented, -1, "Got a JPX PPM segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX PPM marker segment");
return gFalse;
}
}
@@ -1282,8 +1356,8 @@ GBool JPXStream::readCodestream(Guint len) {
// skipped
cover(28);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX TLM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX TLM marker segment");
return gFalse;
}
}
@@ -1292,8 +1366,8 @@ GBool JPXStream::readCodestream(Guint len) {
// skipped
cover(29);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PLM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX PLM marker segment");
return gFalse;
}
}
@@ -1302,8 +1376,8 @@ GBool JPXStream::readCodestream(Guint len) {
// skipped
cover(30);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX CRG marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX CRG marker segment");
return gFalse;
}
}
@@ -1312,8 +1386,8 @@ GBool JPXStream::readCodestream(Guint len) {
// skipped
cover(31);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX COM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX COM marker segment");
return gFalse;
}
}
@@ -1324,9 +1398,10 @@ GBool JPXStream::readCodestream(Guint len) {
break;
default:
cover(33);
- error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
+ error(errSyntaxError, getPos(),
+ "Unknown marker segment {0:02x} in JPX stream", segType);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
+ if (bufStr->getChar() == EOF) {
break;
}
}
@@ -1335,15 +1410,18 @@ GBool JPXStream::readCodestream(Guint len) {
} while (!haveSOT);
if (!haveSIZ) {
- error(getPos(), "Missing SIZ marker segment in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Missing SIZ marker segment in JPX stream");
return gFalse;
}
if (!haveCOD) {
- error(getPos(), "Missing COD marker segment in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Missing COD marker segment in JPX stream");
return gFalse;
}
if (!haveQCD) {
- error(getPos(), "Missing QCD marker segment in JPX stream");
+ error(errSyntaxError, getPos(),
+ "Missing QCD marker segment in JPX stream");
return gFalse;
}
@@ -1353,7 +1431,7 @@ GBool JPXStream::readCodestream(Guint len) {
return gFalse;
}
if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX codestream");
+ error(errSyntaxError, getPos(), "Error in JPX codestream");
return gFalse;
}
if (segType != 0x90) { // SOT - start of tile
@@ -1362,13 +1440,17 @@ GBool JPXStream::readCodestream(Guint len) {
}
if (segType != 0xd9) { // EOC - end of codestream
- error(getPos(), "Missing EOC marker in JPX codestream");
+ error(errSyntaxError, getPos(), "Missing EOC marker in JPX codestream");
return gFalse;
}
//----- finish decoding the image
for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
tile = &img.tiles[i];
+ if (!tile->init) {
+ error(errSyntaxError, getPos(), "Uninitialized tile in JPX codestream");
+ return gFalse;
+ }
for (comp = 0; comp < img.nComps; ++comp) {
tileComp = &tile->tileComps[comp];
inverseTransform(tileComp);
@@ -1390,12 +1472,13 @@ GBool JPXStream::readTilePart() {
JPXPrecinct *precinct;
JPXSubband *subband;
JPXCodeBlock *cb;
+ int *sbCoeffs;
GBool haveSOD;
Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
GBool tilePartToEOC;
Guint precinctSize, style;
Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
- Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
+ Guint i, j, k, cbX, cbY, r, pre, sb, cbi, cbj;
int segType, level;
// process the SOT marker segment
@@ -1403,12 +1486,13 @@ GBool JPXStream::readTilePart() {
!readULong(&tilePartLen) ||
!readUByte(&tilePartIdx) ||
!readUByte(&nTileParts)) {
- error(getPos(), "Error in JPX SOT marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX SOT marker segment");
return gFalse;
}
- if (tileIdx >= img.nXTiles * img.nYTiles) {
- error(getPos(), "Weird tile index in JPX stream");
+ if ((tilePartIdx > 0 && !img.tiles[tileIdx].init) ||
+ tileIdx >= img.nXTiles * img.nYTiles) {
+ error(errSyntaxError, getPos(), "Weird tile index in JPX stream");
return gFalse;
}
@@ -1418,7 +1502,7 @@ GBool JPXStream::readTilePart() {
haveSOD = gFalse;
do {
if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX tile-part codestream");
+ error(errSyntaxError, getPos(), "Error in JPX tile-part codestream");
return gFalse;
}
tilePartLen -= 2 + segLen;
@@ -1434,7 +1518,13 @@ GBool JPXStream::readTilePart() {
!readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
!readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
!readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ if (img.tiles[tileIdx].tileComps[0].nDecompLevels > 32 ||
+ img.tiles[tileIdx].tileComps[0].codeBlockW > 8 ||
+ img.tiles[tileIdx].tileComps[0].codeBlockH > 8) {
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
@@ -1468,7 +1558,7 @@ GBool JPXStream::readTilePart() {
for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
@@ -1502,7 +1592,13 @@ GBool JPXStream::readTilePart() {
!readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
!readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
!readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
- error(getPos(), "Error in JPX COC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
+ return gFalse;
+ }
+ if (img.tiles[tileIdx].tileComps[comp].nDecompLevels > 32 ||
+ img.tiles[tileIdx].tileComps[comp].codeBlockW > 8 ||
+ img.tiles[tileIdx].tileComps[comp].codeBlockH > 8) {
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[tileIdx].tileComps[comp].style =
@@ -1520,7 +1616,7 @@ GBool JPXStream::readTilePart() {
for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
@@ -1536,19 +1632,22 @@ GBool JPXStream::readTilePart() {
case 0x5c: // QCD - quantization default
cover(36);
if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
- img.tiles[tileIdx].tileComps[0].nQuantSteps =
- segLen - 3;
+ if (segLen <= 3) {
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ img.tiles[tileIdx].tileComps[0].nQuantSteps = segLen - 3;
img.tiles[tileIdx].tileComps[0].quantSteps =
(Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
img.tiles[tileIdx].tileComps[0].nQuantSteps,
sizeof(Guint));
for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
@@ -1559,10 +1658,14 @@ GBool JPXStream::readTilePart() {
img.tiles[tileIdx].tileComps[0].nQuantSteps,
sizeof(Guint));
if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
} else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
+ if (segLen < 5) {
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
img.tiles[tileIdx].tileComps[0].quantSteps =
(Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
@@ -1570,12 +1673,12 @@ GBool JPXStream::readTilePart() {
sizeof(Guint));
for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
} else {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
for (comp = 1; comp < img.nComps; ++comp) {
@@ -1599,10 +1702,14 @@ GBool JPXStream::readTilePart() {
(img.nComps <= 256 && !readUByte(&comp)) ||
comp >= img.nComps ||
!readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
+ if (segLen <= (img.nComps > 256 ? 5U : 4U)) {
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
img.tiles[tileIdx].tileComps[comp].nQuantSteps =
segLen - (img.nComps > 256 ? 5 : 4);
img.tiles[tileIdx].tileComps[comp].quantSteps =
@@ -1611,7 +1718,7 @@ GBool JPXStream::readTilePart() {
sizeof(Guint));
for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
}
@@ -1623,11 +1730,15 @@ GBool JPXStream::readTilePart() {
img.tiles[tileIdx].tileComps[comp].nQuantSteps,
sizeof(Guint));
if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
} else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
== 0x02) {
+ if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) {
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
img.tiles[tileIdx].tileComps[comp].nQuantSteps =
(segLen - (img.nComps > 256 ? 5 : 4)) / 2;
img.tiles[tileIdx].tileComps[comp].quantSteps =
@@ -1636,22 +1747,22 @@ GBool JPXStream::readTilePart() {
sizeof(Guint));
for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
return gFalse;
}
}
} else {
- error(getPos(), "Error in JPX QCC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
return gFalse;
}
break;
case 0x5e: // RGN - region of interest
cover(38);
#if 1 //~ ROI is unimplemented
- fprintf(stderr, "RGN\n");
+ error(errUnimplemented, -1, "Got a JPX RGN segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
return gFalse;
}
}
@@ -1661,7 +1772,7 @@ GBool JPXStream::readTilePart() {
comp >= img.nComps ||
!readUByte(&compInfo[comp].roi.style) ||
!readUByte(&compInfo[comp].roi.shift)) {
- error(getPos(), "Error in JPX RGN marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
return gFalse;
}
#endif
@@ -1669,10 +1780,10 @@ GBool JPXStream::readTilePart() {
case 0x5f: // POC - progression order change
cover(39);
#if 1 //~ progression order changes are unimplemented
- fprintf(stderr, "POC\n");
+ error(errUnimplemented, -1, "Got a JPX POC segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
return gFalse;
}
}
@@ -1688,7 +1799,7 @@ GBool JPXStream::readTilePart() {
!(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
!(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
!readUByte(&tileProgs[i].progOrder)) {
- error(getPos(), "Error in JPX POC marker segment");
+ error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
return gFalse;
}
}
@@ -1697,10 +1808,10 @@ GBool JPXStream::readTilePart() {
case 0x61: // PPT - packed packet headers, tile-part hdr
cover(40);
#if 1 //~ packed packet headers are unimplemented
- fprintf(stderr, "PPT\n");
+ error(errUnimplemented, -1, "Got a JPX PPT segment");
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPT marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX PPT marker segment");
return gFalse;
}
}
@@ -1709,8 +1820,8 @@ GBool JPXStream::readTilePart() {
// skipped
cover(41);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PLT marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX PLT marker segment");
return gFalse;
}
}
@@ -1719,8 +1830,8 @@ GBool JPXStream::readTilePart() {
// skipped
cover(42);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX COM marker segment");
+ if (bufStr->getChar() == EOF) {
+ error(errSyntaxError, getPos(), "Error in JPX COM marker segment");
return gFalse;
}
}
@@ -1731,10 +1842,11 @@ GBool JPXStream::readTilePart() {
break;
default:
cover(44);
- error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
+ error(errSyntaxError, getPos(),
+ "Unknown marker segment {0:02x} in JPX tile-part stream",
segType);
for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
+ if (bufStr->getChar() == EOF) {
break;
}
}
@@ -1745,6 +1857,7 @@ GBool JPXStream::readTilePart() {
//----- initialize the tile, precincts, and code-blocks
if (tilePartIdx == 0) {
tile = &img.tiles[tileIdx];
+ tile->init = gTrue;
i = tileIdx / img.nXTiles;
j = tileIdx % img.nXTiles;
if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
@@ -1770,9 +1883,10 @@ GBool JPXStream::readTilePart() {
tile->maxNDecompLevels = tileComp->nDecompLevels;
}
tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
- tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
+ tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep);
tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
- tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
+ tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep);
+ tileComp->w = tileComp->x1 - tileComp->x0;
tileComp->cbW = 1 << tileComp->codeBlockW;
tileComp->cbH = 1 << tileComp->codeBlockH;
tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) *
@@ -1861,6 +1975,19 @@ GBool JPXStream::readTilePart() {
sizeof(JPXCodeBlock));
sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
+ if (r == 0) { // (NL)LL
+ sbCoeffs = tileComp->data;
+ } else if (sb == 0) { // (NL-r+1)HL
+ sbCoeffs = tileComp->data
+ + resLevel->bx1[1] - resLevel->bx0[1];
+ } else if (sb == 1) { // (NL-r+1)LH
+ sbCoeffs = tileComp->data
+ + (resLevel->by1[0] - resLevel->by0[0]) * tileComp->w;
+ } else { // (NL-r+1)HH
+ sbCoeffs = tileComp->data
+ + (resLevel->by1[0] - resLevel->by0[0]) * tileComp->w
+ + resLevel->bx1[1] - resLevel->bx0[1];
+ }
cb = subband->cbs;
for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
@@ -1884,18 +2011,21 @@ GBool JPXStream::readTilePart() {
cb->lBlock = 3;
cb->nextPass = jpxPassCleanup;
cb->nZeroBitPlanes = 0;
- cb->coeffs =
- (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW
- + tileComp->codeBlockH)),
- sizeof(JPXCoeff));
- for (cbi = 0;
- cbi < (Guint)(1 << (tileComp->codeBlockW
- + tileComp->codeBlockH));
- ++cbi) {
- cb->coeffs[cbi].flags = 0;
- cb->coeffs[cbi].len = 0;
- cb->coeffs[cbi].mag = 0;
+ cb->dataLenSize = 1;
+ cb->dataLen = (Guint *)gmalloc(sizeof(Guint));
+ cb->coeffs = sbCoeffs
+ + (cb->y0 - subband->y0) * tileComp->w
+ + (cb->x0 - subband->x0);
+ cb->touched = (char *)gmalloc(1 << (tileComp->codeBlockW
+ + tileComp->codeBlockH));
+ cb->len = 0;
+ for (cbj = 0; cbj < cb->y1 - cb->y0; ++cbj) {
+ for (cbi = 0; cbi < cb->x1 - cb->x0; ++cbi) {
+ cb->coeffs[cbj * tileComp->w + cbi] = 0;
+ }
}
+ memset(cb->touched, 0,
+ (1 << (tileComp->codeBlockW + tileComp->codeBlockH)));
cb->arithDecoder = NULL;
cb->stats = NULL;
++cb;
@@ -1941,6 +2071,9 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
// setup
startBitBuf(tilePartLen);
+ if (tileComp->style & 0x02) {
+ skipSOP();
+ }
// zero-length flag
if (!readBits(1, &bits)) {
@@ -2099,19 +2232,41 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
++cb->lBlock;
}
- // length of compressed data
- //~ deal with multiple codeword segments
- for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
- i;
- ++n, i >>= 1) ;
- if (!readBits(n, &cb->dataLen)) {
- goto err;
+ // one codeword segment for each of the coding passes
+ if (tileComp->codeBlockStyle & 0x04) {
+ if (cb->nCodingPasses > cb->dataLenSize) {
+ cb->dataLenSize = cb->nCodingPasses;
+ cb->dataLen = (Guint *)greallocn(cb->dataLen,
+ cb->dataLenSize,
+ sizeof(Guint));
+ }
+
+ // read the lengths
+ for (i = 0; i < cb->nCodingPasses; ++i) {
+ if (!readBits(cb->lBlock, &cb->dataLen[i])) {
+ goto err;
+ }
+ }
+
+ // one codeword segment for all of the coding passes
+ } else {
+
+ // read the length
+ for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
+ i;
+ ++n, i >>= 1) ;
+ if (!readBits(n, &cb->dataLen[0])) {
+ goto err;
+ }
}
}
}
}
}
}
+ if (tileComp->style & 0x04) {
+ skipEPH();
+ }
tilePartLen = finishBitBuf();
//----- packet data
@@ -2126,7 +2281,13 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->res, sb, cb)) {
return gFalse;
}
- tilePartLen -= cb->dataLen;
+ if (tileComp->codeBlockStyle & 0x04) {
+ for (i = 0; i < cb->nCodingPasses; ++i) {
+ tilePartLen -= cb->dataLen[i];
+ }
+ } else {
+ tilePartLen -= cb->dataLen[0];
+ }
cb->seen = gTrue;
}
}
@@ -2205,7 +2366,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
return gTrue;
err:
- error(getPos(), "Error in JPX stream");
+ error(errSyntaxError, getPos(), "Error in JPX stream");
return gFalse;
}
@@ -2215,18 +2376,20 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
JPXSubband *subband,
Guint res, Guint sb,
JPXCodeBlock *cb) {
- JPXCoeff *coeff0, *coeff1, *coeff;
+ int *coeff0, *coeff1, *coeff;
+ char *touched0, *touched1, *touched;
Guint horiz, vert, diag, all, cx, xorBit;
- int horizSign, vertSign;
- Guint i, x, y0, y1, y2;
+ int horizSign, vertSign, bit;
+ int segSym;
+ Guint i, x, y0, y1;
if (cb->arithDecoder) {
cover(63);
- cb->arithDecoder->restart(cb->dataLen);
+ cb->arithDecoder->restart(cb->dataLen[0]);
} else {
cover(64);
cb->arithDecoder = new JArithmeticDecoder();
- cb->arithDecoder->setStream(str, cb->dataLen);
+ cb->arithDecoder->setStream(bufStr, cb->dataLen[0]);
cb->arithDecoder->start();
cb->stats = new JArithmeticDecoderStats(jpxNContexts);
cb->stats->setEntry(jpxContextSigProp, 4, 0);
@@ -2235,78 +2398,80 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
}
for (i = 0; i < cb->nCodingPasses; ++i) {
+ if ((tileComp->codeBlockStyle & 0x04) && i > 0) {
+ cb->arithDecoder->setStream(bufStr, cb->dataLen[i]);
+ cb->arithDecoder->start();
+ }
+
switch (cb->nextPass) {
//----- significance propagation pass
case jpxPassSigProp:
cover(65);
- for (y0 = cb->y0, coeff0 = cb->coeffs;
+ for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched;
y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
+ y0 += 4, coeff0 += 4 * tileComp->w,
+ touched0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0, touched1 = touched0;
x < cb->x1;
- ++x, ++coeff1) {
- for (y1 = 0, coeff = coeff1;
+ ++x, ++coeff1, ++touched1) {
+ for (y1 = 0, coeff = coeff1, touched = touched1;
y1 < 4 && y0+y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if (!(coeff->flags & jpxCoeffSignificant)) {
+ ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
+ if (!*coeff) {
horiz = vert = diag = 0;
horizSign = vertSign = 2;
if (x > cb->x0) {
- if (coeff[-1].flags & jpxCoeffSignificant) {
+ if (coeff[-1]) {
++horiz;
- horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
+ horizSign += coeff[-1] < 0 ? -1 : 1;
}
if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ diag += coeff[-(int)tileComp->w - 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ diag += coeff[tileComp->w - 1] ? 1 : 0;
}
}
if (x < cb->x1 - 1) {
- if (coeff[1].flags & jpxCoeffSignificant) {
+ if (coeff[1]) {
++horiz;
- horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
+ horizSign += coeff[1] < 0 ? -1 : 1;
}
if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ diag += coeff[-(int)tileComp->w + 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ diag += coeff[tileComp->w + 1] ? 1 : 0;
}
}
if (y0+y1 > cb->y0) {
- if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
+ if (coeff[-(int)tileComp->w]) {
++vert;
- vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
+ vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1;
}
}
- if (y0+y1 < cb->y1 - 1) {
- if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ if (coeff[tileComp->w]) {
++vert;
- vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
+ vertSign += coeff[tileComp->w] < 0 ? -1 : 1;
}
}
cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
if (cx != 0) {
if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
cx = signContext[horizSign][vertSign][0];
xorBit = signContext[horizSign][vertSign][1];
if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
+ *coeff = -1;
+ } else {
+ *coeff = 1;
}
}
- ++coeff->len;
- coeff->flags |= jpxCoeffTouched;
+ *touched = 1;
}
}
}
@@ -2318,58 +2483,57 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
//----- magnitude refinement pass
case jpxPassMagRef:
cover(66);
- for (y0 = cb->y0, coeff0 = cb->coeffs;
+ for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched;
y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
+ y0 += 4, coeff0 += 4 * tileComp->w,
+ touched0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0, touched1 = touched0;
x < cb->x1;
- ++x, ++coeff1) {
- for (y1 = 0, coeff = coeff1;
+ ++x, ++coeff1, ++touched1) {
+ for (y1 = 0, coeff = coeff1, touched = touched1;
y1 < 4 && y0+y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if ((coeff->flags & jpxCoeffSignificant) &&
- !(coeff->flags & jpxCoeffTouched)) {
- if (coeff->flags & jpxCoeffFirstMagRef) {
+ ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
+ if (*coeff && !*touched) {
+ if (*coeff == 1 || *coeff == -1) {
all = 0;
if (x > cb->x0) {
- all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
+ all += coeff[-1] ? 1 : 0;
if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ all += coeff[-(int)tileComp->w - 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ all += coeff[tileComp->w - 1] ? 1 : 0;
}
}
if (x < cb->x1 - 1) {
- all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
+ all += coeff[1] ? 1 : 0;
if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ all += coeff[-(int)tileComp->w + 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ all += coeff[tileComp->w + 1] ? 1 : 0;
}
}
if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW].flags
- >> jpxCoeffSignificantB) & 1;
+ all += coeff[-(int)tileComp->w] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ all += coeff[tileComp->w] ? 1 : 0;
}
cx = all ? 15 : 14;
} else {
cx = 16;
}
- coeff->mag = (coeff->mag << 1) |
- cb->arithDecoder->decodeBit(cx, cb->stats);
- ++coeff->len;
- coeff->flags |= jpxCoeffTouched;
- coeff->flags &= ~jpxCoeffFirstMagRef;
+ bit = cb->arithDecoder->decodeBit(cx, cb->stats);
+ if (*coeff < 0) {
+ *coeff = (*coeff << 1) - bit;
+ } else {
+ *coeff = (*coeff << 1) + bit;
+ }
+ *touched = 1;
}
}
}
@@ -2380,145 +2544,153 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
//----- cleanup pass
case jpxPassCleanup:
cover(67);
- for (y0 = cb->y0, coeff0 = cb->coeffs;
+ for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched;
y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
+ y0 += 4, coeff0 += 4 * tileComp->w,
+ touched0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0, touched1 = touched0;
x < cb->x1;
- ++x, ++coeff1) {
+ ++x, ++coeff1, ++touched1) {
y1 = 0;
if (y0 + 3 < cb->y1 &&
- !(coeff1->flags & jpxCoeffTouched) &&
- !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
- !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
- !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
+ !(*touched1) &&
+ !(touched1[tileComp->cbW]) &&
+ !(touched1[2 * tileComp->cbW]) &&
+ !(touched1[3 * tileComp->cbW]) &&
(x == cb->x0 || y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW - 1].flags
- & jpxCoeffSignificant)) &&
+ !coeff1[-(int)tileComp->w - 1]) &&
(y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW].flags
- & jpxCoeffSignificant)) &&
+ !coeff1[-(int)tileComp->w]) &&
(x == cb->x1 - 1 || y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW + 1].flags
- & jpxCoeffSignificant)) &&
+ !coeff1[-(int)tileComp->w + 1]) &&
(x == cb->x0 ||
- (!(coeff1[-1].flags & jpxCoeffSignificant) &&
- !(coeff1[tileComp->cbW - 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[2 * tileComp->cbW - 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[3 * tileComp->cbW - 1].flags
- & jpxCoeffSignificant))) &&
+ (!coeff1[-1] &&
+ !coeff1[tileComp->w - 1] &&
+ !coeff1[2 * tileComp->w - 1] &&
+ !coeff1[3 * tileComp->w - 1])) &&
(x == cb->x1 - 1 ||
- (!(coeff1[1].flags & jpxCoeffSignificant) &&
- !(coeff1[tileComp->cbW + 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[2 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[3 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant))) &&
- (x == cb->x0 || y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
- (y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
- (x == cb->x1 - 1 || y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant))) {
+ (!coeff1[1] &&
+ !coeff1[tileComp->w + 1] &&
+ !coeff1[2 * tileComp->w + 1] &&
+ !coeff1[3 * tileComp->w + 1])) &&
+ ((tileComp->codeBlockStyle & 0x08) ||
+ ((x == cb->x0 || y0+4 == cb->y1 ||
+ !coeff1[4 * tileComp->w - 1]) &&
+ (y0+4 == cb->y1 ||
+ !coeff1[4 * tileComp->w]) &&
+ (x == cb->x1 - 1 || y0+4 == cb->y1 ||
+ !coeff1[4 * tileComp->w + 1])))) {
if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
y1 = (y1 << 1) |
cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
- for (y2 = 0, coeff = coeff1;
- y2 < y1;
- ++y2, coeff += tileComp->cbW) {
- ++coeff->len;
- }
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
- ++coeff->len;
+ coeff = &coeff1[y1 * tileComp->w];
cx = signContext[2][2][0];
xorBit = signContext[2][2][1];
if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
+ *coeff = -1;
+ } else {
+ *coeff = 1;
}
++y1;
} else {
- for (y1 = 0, coeff = coeff1;
- y1 < 4;
- ++y1, coeff += tileComp->cbW) {
- ++coeff->len;
- }
y1 = 4;
}
}
- for (coeff = &coeff1[y1 << tileComp->codeBlockW];
+ for (coeff = &coeff1[y1 * tileComp->w],
+ touched = &touched1[y1 << tileComp->codeBlockW];
y1 < 4 && y0 + y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if (!(coeff->flags & jpxCoeffTouched)) {
+ ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
+ if (!*touched) {
horiz = vert = diag = 0;
horizSign = vertSign = 2;
if (x > cb->x0) {
- if (coeff[-1].flags & jpxCoeffSignificant) {
+ if (coeff[-1]) {
++horiz;
- horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
+ horizSign += coeff[-1] < 0 ? -1 : 1;
}
if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ diag += coeff[-(int)tileComp->w - 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ diag += coeff[tileComp->w - 1] ? 1 : 0;
}
}
if (x < cb->x1 - 1) {
- if (coeff[1].flags & jpxCoeffSignificant) {
+ if (coeff[1]) {
++horiz;
- horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
+ horizSign += coeff[1] < 0 ? -1 : 1;
}
if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ diag += coeff[-(int)tileComp->w + 1] ? 1 : 0;
}
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ diag += coeff[tileComp->w + 1] ? 1 : 0;
}
}
if (y0+y1 > cb->y0) {
- if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
+ if (coeff[-(int)tileComp->w]) {
++vert;
- vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
+ vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1;
}
}
- if (y0+y1 < cb->y1 - 1) {
- if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
+ if (y0+y1 < cb->y1 - 1 &&
+ (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
+ if (coeff[tileComp->w]) {
++vert;
- vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
+ vertSign += coeff[tileComp->w] < 0 ? -1 : 1;
}
}
cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
cx = signContext[horizSign][vertSign][0];
xorBit = signContext[horizSign][vertSign][1];
if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
+ *coeff = -1;
+ } else {
+ *coeff = 1;
}
}
- ++coeff->len;
} else {
- coeff->flags &= ~jpxCoeffTouched;
+ *touched = 0;
}
}
}
}
+ ++cb->len;
+ // look for a segmentation symbol
+ if (tileComp->codeBlockStyle & 0x20) {
+ segSym = cb->arithDecoder->decodeBit(jpxContextUniform,
+ cb->stats) << 3;
+ segSym |= cb->arithDecoder->decodeBit(jpxContextUniform,
+ cb->stats) << 2;
+ segSym |= cb->arithDecoder->decodeBit(jpxContextUniform,
+ cb->stats) << 1;
+ segSym |= cb->arithDecoder->decodeBit(jpxContextUniform,
+ cb->stats);
+ if (segSym != 0x0a) {
+ // in theory this should be a fatal error, but it seems to
+ // be problematic
+ error(errSyntaxWarning, getPos(),
+ "Missing or invalid segmentation symbol in JPX stream");
+ }
+ }
cb->nextPass = jpxPassSigProp;
break;
}
+
+ if (tileComp->codeBlockStyle & 0x02) {
+ cb->stats->reset();
+ cb->stats->setEntry(jpxContextSigProp, 4, 0);
+ cb->stats->setEntry(jpxContextRunLength, 3, 0);
+ cb->stats->setEntry(jpxContextUniform, 46, 0);
+ }
+
+ if (tileComp->codeBlockStyle & 0x04) {
+ cb->arithDecoder->cleanup();
+ }
}
cb->arithDecoder->cleanup();
@@ -2532,13 +2704,12 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
JPXPrecinct *precinct;
JPXSubband *subband;
JPXCodeBlock *cb;
- JPXCoeff *coeff0, *coeff;
+ int *coeff0, *coeff;
+ char *touched0, *touched;
Guint qStyle, guard, eps, shift;
int shift2;
double mu;
int val;
- int *dataPtr;
- Guint nx0, ny0, nx1, ny1;
Guint r, cbX, cbY, x, y;
cover(68);
@@ -2567,24 +2738,26 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
shift += fracBits;
}
- // copy (NL)LL into the upper-left corner of the data array, doing
- // the fixed point adjustment and dequantization along the way
+ // do fixed point adjustment and dequantization on (NL)LL
cb = subband->cbs;
for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- for (y = cb->y0, coeff0 = cb->coeffs;
+ for (y = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched;
y < cb->y1;
- ++y, coeff0 += tileComp->cbW) {
- dataPtr = &tileComp->data[(y - subband->y0)
- * (tileComp->x1 - tileComp->x0)
- + (cb->x0 - subband->x0)];
- for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
- val = (int)coeff->mag;
+ ++y, coeff0 += tileComp->w, touched0 += tileComp->cbW) {
+ for (x = cb->x0, coeff = coeff0, touched = touched0;
+ x < cb->x1;
+ ++x, ++coeff, ++touched) {
+ val = *coeff;
if (val != 0) {
- shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
+ shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched);
if (shift2 > 0) {
cover(94);
- val = (val << shift2) + (1 << (shift2 - 1));
+ if (val < 0) {
+ val = (val << shift2) - (1 << (shift2 - 1));
+ } else {
+ val = (val << shift2) + (1 << (shift2 - 1));
+ }
} else {
cover(95);
val >>= -shift2;
@@ -2599,12 +2772,8 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
cover(98);
val = (int)((double)val * mu);
}
- if (coeff->flags & jpxCoeffSign) {
- cover(99);
- val = -val;
- }
}
- *dataPtr++ = val;
+ *coeff = val;
}
}
++cb;
@@ -2620,61 +2789,33 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
// tile-component data array -- interleave with (n)HL/LH/HH
// 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;
- ny1 = tileComp->resLevels[r+1].y1;
- }
- inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
+ inverseTransformLevel(tileComp, r, resLevel);
}
}
// Do one level of the inverse transform:
-// - take (n)LL from the tile-component data array
-// - take (n)HL/LH/HH from <resLevel>
-// - leave the resulting (n-1)LL in the tile-component data array
+// - take (n)LL, (n)HL, (n)LH, and (n)HH from the upper-left corner
+// of the tile-component data array
+// - leave the resulting (n-1)LL in the same place
void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
- Guint r, JPXResLevel *resLevel,
- Guint nx0, Guint ny0,
- Guint nx1, Guint ny1) {
+ Guint r, JPXResLevel *resLevel) {
JPXPrecinct *precinct;
JPXSubband *subband;
JPXCodeBlock *cb;
- JPXCoeff *coeff0, *coeff;
+ int *coeff0, *coeff;
+ char *touched0, *touched;
Guint qStyle, guard, eps, shift, t;
int shift2;
double mu;
int val;
- int *dataPtr;
- Guint xo, yo;
+ int *dataPtr, *bufPtr;
+ Guint nx1, nx2, ny1, ny2, offset;
Guint x, y, sb, cbX, cbY;
- int xx, yy;
-
- //----- interleave
- // spread out LL
- for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
- for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
- tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
- + (2 * xx - nx0)] =
- tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
- + (xx - resLevel->x0)];
- }
- }
+ //----- fixed-point adjustment and dequantization
- // i-quant parameters
qStyle = tileComp->quantStyle & 0x1f;
guard = (tileComp->quantStyle >> 5) & 7;
-
- // interleave HL/LH/HH
precinct = &resLevel->precincts[0];
for (sb = 0; sb < 3; ++sb) {
@@ -2699,27 +2840,27 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
shift += fracBits;
}
- // copy the subband coefficients into the data array, doing the
- // fixed point adjustment and dequantization along the way
- xo = (sb & 1) ? 0 : 1;
- yo = (sb > 0) ? 1 : 0;
+ // fixed point adjustment and dequantization
subband = &precinct->subbands[sb];
cb = subband->cbs;
for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- for (y = cb->y0, coeff0 = cb->coeffs;
+ for (y = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched;
y < cb->y1;
- ++y, coeff0 += tileComp->cbW) {
- dataPtr = &tileComp->data[(2 * y + yo - ny0)
- * (tileComp->x1 - tileComp->x0)
- + (2 * cb->x0 + xo - nx0)];
- for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
- val = (int)coeff->mag;
+ ++y, coeff0 += tileComp->w, touched0 += tileComp->cbW) {
+ for (x = cb->x0, coeff = coeff0, touched = touched0;
+ x < cb->x1;
+ ++x, ++coeff, ++touched) {
+ val = *coeff;
if (val != 0) {
- shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
+ shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched);
if (shift2 > 0) {
cover(74);
- val = (val << shift2) + (1 << (shift2 - 1));
+ if (val < 0) {
+ val = (val << shift2) - (1 << (shift2 - 1));
+ } else {
+ val = (val << shift2) + (1 << (shift2 - 1));
+ }
} else {
cover(75);
val >>= -shift2;
@@ -2733,13 +2874,8 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
cover(77);
val = (int)((double)val * mu);
}
- if (coeff->flags & jpxCoeffSign) {
- cover(78);
- val = -val;
- }
}
- *dataPtr = val;
- dataPtr += 2;
+ *coeff = val;
}
}
++cb;
@@ -2747,32 +2883,112 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
}
}
- //----- horizontal (row) transforms
- dataPtr = tileComp->data;
- for (y = 0; y < ny1 - ny0; ++y) {
- inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
- dataPtr += tileComp->x1 - tileComp->x0;
+ //----- inverse transform
+
+ // compute the subband bounds:
+ // 0 nx1 nx2
+ // | | |
+ // v v v
+ // +----+----+
+ // | LL | HL | <- 0
+ // +----+----+
+ // | LH | HH | <- ny1
+ // +----+----+
+ // <- ny2
+ nx1 = precinct->subbands[1].x1 - precinct->subbands[1].x0;
+ nx2 = nx1 + precinct->subbands[0].x1 - precinct->subbands[0].x0;
+ ny1 = precinct->subbands[0].y1 - precinct->subbands[0].y0;
+ ny2 = ny1 + precinct->subbands[1].y1 - precinct->subbands[1].y0;
+
+ // horizontal (row) transforms
+ if (r == tileComp->nDecompLevels) {
+ offset = 3 + (tileComp->x0 & 1);
+ } else {
+ offset = 3 + (tileComp->resLevels[r+1].x0 & 1);
+ }
+ for (y = 0, dataPtr = tileComp->data; y < ny2; ++y, dataPtr += tileComp->w) {
+ if (precinct->subbands[0].x0 == precinct->subbands[1].x0) {
+ // fetch LL/LH
+ for (x = 0, bufPtr = tileComp->buf + offset;
+ x < nx1;
+ ++x, bufPtr += 2) {
+ *bufPtr = dataPtr[x];
+ }
+ // fetch HL/HH
+ for (x = nx1, bufPtr = tileComp->buf + offset + 1;
+ x < nx2;
+ ++x, bufPtr += 2) {
+ *bufPtr = dataPtr[x];
+ }
+ } else {
+ // fetch LL/LH
+ for (x = 0, bufPtr = tileComp->buf + offset + 1;
+ x < nx1;
+ ++x, bufPtr += 2) {
+ *bufPtr = dataPtr[x];
+ }
+ // fetch HL/HH
+ for (x = nx1, bufPtr = tileComp->buf + offset;
+ x < nx2;
+ ++x, bufPtr += 2) {
+ *bufPtr = dataPtr[x];
+ }
+ }
+ inverseTransform1D(tileComp, tileComp->buf, offset, nx2);
+ for (x = 0, bufPtr = tileComp->buf + offset; x < nx2; ++x, ++bufPtr) {
+ dataPtr[x] = *bufPtr;
+ }
}
- //----- vertical (column) transforms
- dataPtr = tileComp->data;
- for (x = 0; x < nx1 - nx0; ++x) {
- inverseTransform1D(tileComp, dataPtr,
- tileComp->x1 - tileComp->x0, ny0, ny1);
- ++dataPtr;
+ // vertical (column) transforms
+ if (r == tileComp->nDecompLevels) {
+ offset = 3 + (tileComp->y0 & 1);
+ } else {
+ offset = 3 + (tileComp->resLevels[r+1].y0 & 1);
+ }
+ for (x = 0, dataPtr = tileComp->data; x < nx2; ++x, ++dataPtr) {
+ if (precinct->subbands[1].y0 == precinct->subbands[0].y0) {
+ // fetch LL/HL
+ for (y = 0, bufPtr = tileComp->buf + offset;
+ y < ny1;
+ ++y, bufPtr += 2) {
+ *bufPtr = dataPtr[y * tileComp->w];
+ }
+ // fetch LH/HH
+ for (y = ny1, bufPtr = tileComp->buf + offset + 1;
+ y < ny2;
+ ++y, bufPtr += 2) {
+ *bufPtr = dataPtr[y * tileComp->w];
+ }
+ } else {
+ // fetch LL/HL
+ for (y = 0, bufPtr = tileComp->buf + offset + 1;
+ y < ny1;
+ ++y, bufPtr += 2) {
+ *bufPtr = dataPtr[y * tileComp->w];
+ }
+ // fetch LH/HH
+ for (y = ny1, bufPtr = tileComp->buf + offset;
+ y < ny2;
+ ++y, bufPtr += 2) {
+ *bufPtr = dataPtr[y * tileComp->w];
+ }
+ }
+ inverseTransform1D(tileComp, tileComp->buf, offset, ny2);
+ for (y = 0, bufPtr = tileComp->buf + offset; y < ny2; ++y, ++bufPtr) {
+ dataPtr[y * tileComp->w] = *bufPtr;
+ }
}
}
-void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
- int *data, Guint stride,
- Guint i0, Guint i1) {
- int *buf;
- Guint offset, end, i;
+void JPXStream::inverseTransform1D(JPXTileComp *tileComp, int *data,
+ Guint offset, Guint n) {
+ Guint end, i;
//----- special case for length = 1
- if (i1 - i0 == 1) {
+ if (n == 1) {
cover(79);
- if (i0 & 1) {
+ if (offset == 4) {
cover(104);
*data >>= 1;
}
@@ -2780,51 +2996,42 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
} else {
cover(80);
- // choose an offset: this makes even buf[] indexes correspond to
- // odd values of i, and vice versa
- offset = 3 + (i0 & 1);
- end = offset + i1 - i0;
-
- //----- gather
- buf = tileComp->buf;
- for (i = 0; i < i1 - i0; ++i) {
- buf[offset + i] = data[i * stride];
- }
+ end = offset + n;
//----- extend right
- buf[end] = buf[end - 2];
- if (i1 - i0 == 2) {
+ data[end] = data[end - 2];
+ if (n == 2) {
cover(81);
- buf[end+1] = buf[offset + 1];
- buf[end+2] = buf[offset];
- buf[end+3] = buf[offset + 1];
+ data[end+1] = data[offset + 1];
+ data[end+2] = data[offset];
+ data[end+3] = data[offset + 1];
} else {
cover(82);
- buf[end+1] = buf[end - 3];
- if (i1 - i0 == 3) {
+ data[end+1] = data[end - 3];
+ if (n == 3) {
cover(105);
- buf[end+2] = buf[offset + 1];
- buf[end+3] = buf[offset + 2];
+ data[end+2] = data[offset + 1];
+ data[end+3] = data[offset + 2];
} else {
cover(106);
- buf[end+2] = buf[end - 4];
- if (i1 - i0 == 4) {
+ data[end+2] = data[end - 4];
+ if (n == 4) {
cover(107);
- buf[end+3] = buf[offset + 1];
+ data[end+3] = data[offset + 1];
} else {
cover(108);
- buf[end+3] = buf[end - 5];
+ data[end+3] = data[end - 5];
}
}
}
//----- extend left
- buf[offset - 1] = buf[offset + 1];
- buf[offset - 2] = buf[offset + 2];
- buf[offset - 3] = buf[offset + 3];
+ data[offset - 1] = data[offset + 1];
+ data[offset - 2] = data[offset + 2];
+ data[offset - 3] = data[offset + 3];
if (offset == 4) {
cover(83);
- buf[0] = buf[offset + 4];
+ data[0] = data[offset + 4];
}
//----- 9-7 irreversible filter
@@ -2833,27 +3040,27 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
cover(84);
// step 1 (even)
for (i = 1; i <= end + 2; i += 2) {
- buf[i] = (int)(idwtKappa * buf[i]);
+ data[i] = (int)(idwtKappa * data[i]);
}
// step 2 (odd)
for (i = 0; i <= end + 3; i += 2) {
- buf[i] = (int)(idwtIKappa * buf[i]);
+ data[i] = (int)(idwtIKappa * data[i]);
}
// step 3 (even)
for (i = 1; i <= end + 2; i += 2) {
- buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
+ data[i] = (int)(data[i] - idwtDelta * (data[i-1] + data[i+1]));
}
// step 4 (odd)
for (i = 2; i <= end + 1; i += 2) {
- buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
+ data[i] = (int)(data[i] - idwtGamma * (data[i-1] + data[i+1]));
}
// step 5 (even)
for (i = 3; i <= end; i += 2) {
- buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
+ data[i] = (int)(data[i] - idwtBeta * (data[i-1] + data[i+1]));
}
// step 6 (odd)
for (i = 4; i <= end - 1; i += 2) {
- buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
+ data[i] = (int)(data[i] - idwtAlpha * (data[i-1] + data[i+1]));
}
//----- 5-3 reversible filter
@@ -2862,18 +3069,13 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
cover(85);
// step 1 (even)
for (i = 3; i <= end; i += 2) {
- buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
+ data[i] -= (data[i-1] + data[i+1] + 2) >> 2;
}
// step 2 (odd)
for (i = 4; i < end; i += 2) {
- buf[i] += (buf[i-1] + buf[i+1]) >> 1;
+ data[i] += (data[i-1] + data[i+1]) >> 1;
}
}
-
- //----- scatter
- for (i = 0; i < i1 - i0; ++i) {
- data[i * stride] = buf[offset + i];
- }
}
}
@@ -3002,7 +3204,8 @@ GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
return gFalse;
}
if (lenH) {
- error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
+ error(errSyntaxError, getPos(),
+ "JPX stream contains a box larger than 2^32 bytes");
return gFalse;
}
*boxLen = len;
@@ -3022,12 +3225,12 @@ int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
do {
do {
- if ((c = str->getChar()) == EOF) {
+ if ((c = bufStr->getChar()) == EOF) {
return gFalse;
}
} while (c != 0xff);
do {
- if ((c = str->getChar()) == EOF) {
+ if ((c = bufStr->getChar()) == EOF) {
return gFalse;
}
} while (c == 0xff);
@@ -3044,7 +3247,7 @@ int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
GBool JPXStream::readUByte(Guint *x) {
int c0;
- if ((c0 = str->getChar()) == EOF) {
+ if ((c0 = bufStr->getChar()) == EOF) {
return gFalse;
}
*x = (Guint)c0;
@@ -3054,7 +3257,7 @@ GBool JPXStream::readUByte(Guint *x) {
GBool JPXStream::readByte(int *x) {
int c0;
- if ((c0 = str->getChar()) == EOF) {
+ if ((c0 = bufStr->getChar()) == EOF) {
return gFalse;
}
*x = c0;
@@ -3067,8 +3270,8 @@ GBool JPXStream::readByte(int *x) {
GBool JPXStream::readUWord(Guint *x) {
int c0, c1;
- if ((c0 = str->getChar()) == EOF ||
- (c1 = str->getChar()) == EOF) {
+ if ((c0 = bufStr->getChar()) == EOF ||
+ (c1 = bufStr->getChar()) == EOF) {
return gFalse;
}
*x = (Guint)((c0 << 8) | c1);
@@ -3078,10 +3281,10 @@ GBool JPXStream::readUWord(Guint *x) {
GBool JPXStream::readULong(Guint *x) {
int c0, c1, c2, c3;
- if ((c0 = str->getChar()) == EOF ||
- (c1 = str->getChar()) == EOF ||
- (c2 = str->getChar()) == EOF ||
- (c3 = str->getChar()) == EOF) {
+ if ((c0 = bufStr->getChar()) == EOF ||
+ (c1 = bufStr->getChar()) == EOF ||
+ (c2 = bufStr->getChar()) == EOF ||
+ (c3 = bufStr->getChar()) == EOF) {
return gFalse;
}
*x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
@@ -3093,7 +3296,7 @@ GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
y = 0;
for (i = 0; i < nBytes; ++i) {
- if ((c = str->getChar()) == EOF) {
+ if ((c = bufStr->getChar()) == EOF) {
return gFalse;
}
y = (y << 8) + c;
@@ -3107,11 +3310,17 @@ GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
return gTrue;
}
+void JPXStream::startBitBuf(Guint byteCountA) {
+ bitBufLen = 0;
+ bitBufSkip = gFalse;
+ byteCount = byteCountA;
+}
+
GBool JPXStream::readBits(int nBits, Guint *x) {
int c;
while (bitBufLen < nBits) {
- if (byteCount == 0 || (c = str->getChar()) == EOF) {
+ if (byteCount == 0 || (c = bufStr->getChar()) == EOF) {
return gFalse;
}
--byteCount;
@@ -3129,15 +3338,42 @@ GBool JPXStream::readBits(int nBits, Guint *x) {
return gTrue;
}
-void JPXStream::startBitBuf(Guint byteCountA) {
- bitBufLen = 0;
- bitBufSkip = gFalse;
- byteCount = byteCountA;
+void JPXStream::skipSOP() {
+ int i;
+
+ // SOP occurs at the start of the packet header, so we don't need to
+ // worry about bit-stuff prior to it
+ if (byteCount >= 6 &&
+ bufStr->lookChar(0) == 0xff &&
+ bufStr->lookChar(1) == 0x91) {
+ for (i = 0; i < 6; ++i) {
+ bufStr->getChar();
+ }
+ byteCount -= 6;
+ bitBufLen = 0;
+ bitBufSkip = gFalse;
+ }
+}
+
+void JPXStream::skipEPH() {
+ int i, k;
+
+ k = bitBufSkip ? 1 : 0;
+ if (byteCount >= (Guint)(k + 2) &&
+ bufStr->lookChar(k) == 0xff &&
+ bufStr->lookChar(k + 1) == 0x92) {
+ for (i = 0; i < k + 2; ++i) {
+ bufStr->getChar();
+ }
+ byteCount -= k + 2;
+ bitBufLen = 0;
+ bitBufSkip = gFalse;
+ }
}
Guint JPXStream::finishBitBuf() {
if (bitBufSkip) {
- str->getChar();
+ bufStr->getChar();
--byteCount;
}
return byteCount;
diff --git a/xpdf/JPXStream.h b/xpdf/JPXStream.h
index e96e7d3..2c46ca0 100644
--- a/xpdf/JPXStream.h
+++ b/xpdf/JPXStream.h
@@ -101,24 +101,6 @@ struct JPXTagTreeNode {
//------------------------------------------------------------------------
-struct JPXCoeff {
- Gushort flags; // flag bits
- Gushort len; // number of significant bits in mag
- Guint mag; // magnitude value
-};
-
-// coefficient flags
-#define jpxCoeffSignificantB 0
-#define jpxCoeffTouchedB 1
-#define jpxCoeffFirstMagRefB 2
-#define jpxCoeffSignB 7
-#define jpxCoeffSignificant (1 << jpxCoeffSignificantB)
-#define jpxCoeffTouched (1 << jpxCoeffTouchedB)
-#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB)
-#define jpxCoeffSign (1 << jpxCoeffSignB)
-
-//------------------------------------------------------------------------
-
struct JPXCodeBlock {
//----- size
Guint x0, y0, x1, y1; // bounds
@@ -136,10 +118,13 @@ struct JPXCodeBlock {
Guint included; // code-block inclusion in this packet:
// 0=not included, 1=included
Guint nCodingPasses; // number of coding passes in this pkt
- Guint dataLen; // pkt data length
+ Guint *dataLen; // data lengths (one per codeword segment)
+ Guint dataLenSize; // size of the dataLen array
//----- coefficient data
- JPXCoeff *coeffs; // the coefficients
+ int *coeffs;
+ char *touched; // coefficient 'touched' flags
+ Gushort len; // coefficient length
JArithmeticDecoder // arithmetic decoder
*arithDecoder;
JArithmeticDecoderStats // arithmetic decoder stats
@@ -214,6 +199,7 @@ struct JPXTileComp {
//----- computed
Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords
+ Guint w; // x1 - x0
Guint cbW; // code-block width
Guint cbH; // code-block height
@@ -230,6 +216,8 @@ struct JPXTileComp {
//------------------------------------------------------------------------
struct JPXTile {
+ GBool init;
+
//----- from the COD segments (main and tile)
Guint progOrder; // progression order
Guint nLayers; // number of layers
@@ -281,7 +269,7 @@ public:
virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
virtual void getImageParams(int *bitsPerComponent,
StreamColorSpaceMode *csMode);
@@ -304,12 +292,9 @@ private:
JPXCodeBlock *cb);
void inverseTransform(JPXTileComp *tileComp);
void inverseTransformLevel(JPXTileComp *tileComp,
- Guint r, JPXResLevel *resLevel,
- Guint nx0, Guint ny0,
- Guint nx1, Guint ny1);
- void inverseTransform1D(JPXTileComp *tileComp,
- int *data, Guint stride,
- Guint i0, Guint i1);
+ Guint r, JPXResLevel *resLevel);
+ void inverseTransform1D(JPXTileComp *tileComp, int *data,
+ Guint offset, Guint n);
GBool inverseMultiCompAndDC(JPXTile *tile);
GBool readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen);
int readMarkerHdr(int *segType, Guint *segLen);
@@ -318,10 +303,14 @@ private:
GBool readUWord(Guint *x);
GBool readULong(Guint *x);
GBool readNBytes(int nBytes, GBool signd, int *x);
- GBool readBits(int nBits, Guint *x);
void startBitBuf(Guint byteCountA);
+ GBool readBits(int nBits, Guint *x);
+ void skipSOP();
+ void skipEPH();
Guint finishBitBuf();
+ BufStream *bufStr; // buffered stream (for lookahead)
+
Guint nComps; // number of components
Guint *bpc; // bits per component, for each component
Guint width, height; // image size
diff --git a/xpdf/Lexer.cc b/xpdf/Lexer.cc
index 9f0c3ca..0589756 100644
--- a/xpdf/Lexer.cc
+++ b/xpdf/Lexer.cc
@@ -142,19 +142,20 @@ Object *Lexer::getObj(Object *obj) {
case '5': case '6': case '7': case '8': case '9':
case '-': case '.':
neg = gFalse;
- xi = 0;
+ xf = xi = 0;
if (c == '-') {
neg = gTrue;
} else if (c == '.') {
goto doReal;
} else {
- xi = c - '0';
+ xf = xi = c - '0';
}
while (1) {
c = lookChar();
if (isdigit(c)) {
getChar();
xi = xi * 10 + (c - '0');
+ xf = xf * 10 + (c - '0');
} else if (c == '.') {
getChar();
goto doReal;
@@ -162,19 +163,19 @@ Object *Lexer::getObj(Object *obj) {
break;
}
}
- if (neg)
+ if (neg) {
xi = -xi;
+ }
obj->initInt(xi);
break;
doReal:
- xf = xi;
scale = 0.1;
while (1) {
c = lookChar();
if (c == '-') {
// ignore minus signs in the middle of numbers to match
// Adobe's behavior
- error(getPos(), "Badly formatted number");
+ error(errSyntaxWarning, getPos(), "Badly formatted number");
getChar();
continue;
}
@@ -185,8 +186,9 @@ Object *Lexer::getObj(Object *obj) {
xf = xf + scale * (c - '0');
scale *= 0.1;
}
- if (neg)
+ if (neg) {
xf = -xf;
+ }
obj->initReal(xf);
break;
@@ -207,7 +209,7 @@ Object *Lexer::getObj(Object *obj) {
case '\r':
case '\n':
#endif
- error(getPos(), "Unterminated string");
+ error(errSyntaxError, getPos(), "Unterminated string");
done = gTrue;
break;
@@ -269,7 +271,7 @@ Object *Lexer::getObj(Object *obj) {
case '\n':
break;
case EOF:
- error(getPos(), "Unterminated string");
+ error(errSyntaxError, getPos(), "Unterminated string");
done = gTrue;
break;
default:
@@ -307,6 +309,7 @@ Object *Lexer::getObj(Object *obj) {
case '/':
p = tokBuf;
n = 0;
+ s = NULL;
while ((c = lookChar()) != EOF && !specialChars[c]) {
getChar();
if (c == '#') {
@@ -330,18 +333,30 @@ Object *Lexer::getObj(Object *obj) {
} else if (c2 >= 'a' && c2 <= 'f') {
c += c2 - 'a' + 10;
} else {
- error(getPos(), "Illegal digit in hex char in name");
+ error(errSyntaxError, getPos(), "Illegal digit in hex char in name");
}
}
notEscChar:
- if (++n == tokBufSize) {
- error(getPos(), "Name token too long");
- break;
+ // the PDF spec claims that names are limited to 127 chars, but
+ // Distiller 8 will produce longer names, and Acrobat 8 will
+ // accept longer names
+ ++n;
+ if (n < tokBufSize) {
+ *p++ = c;
+ } else if (n == tokBufSize) {
+ *p = c;
+ s = new GString(tokBuf, n);
+ } else {
+ s->append((char)c);
}
- *p++ = c;
}
- *p = '\0';
- obj->initName(tokBuf);
+ if (n < tokBufSize) {
+ *p = '\0';
+ obj->initName(tokBuf);
+ } else {
+ obj->initName(s->getCString());
+ delete s;
+ }
break;
// array punctuation
@@ -374,7 +389,7 @@ Object *Lexer::getObj(Object *obj) {
if (c == '>') {
break;
} else if (c == EOF) {
- error(getPos(), "Unterminated hex string");
+ error(errSyntaxError, getPos(), "Unterminated hex string");
break;
} else if (specialChars[c] != 1) {
c2 = c2 << 4;
@@ -385,7 +400,8 @@ Object *Lexer::getObj(Object *obj) {
else if (c >= 'a' && c <= 'f')
c2 += c - 'a' + 10;
else
- error(getPos(), "Illegal character <%02x> in hex string", c);
+ error(errSyntaxError, getPos(),
+ "Illegal character <{0:02x}> in hex string", c);
if (++m == 2) {
if (n == tokBufSize) {
if (!s)
@@ -421,7 +437,7 @@ Object *Lexer::getObj(Object *obj) {
tokBuf[2] = '\0';
obj->initCmd(tokBuf);
} else {
- error(getPos(), "Illegal character '>'");
+ error(errSyntaxError, getPos(), "Illegal character '>'");
obj->initError();
}
break;
@@ -430,7 +446,7 @@ Object *Lexer::getObj(Object *obj) {
case ')':
case '{':
case '}':
- error(getPos(), "Illegal character '%c'", c);
+ error(errSyntaxError, getPos(), "Illegal character '{0:c}'", c);
obj->initError();
break;
@@ -442,7 +458,7 @@ Object *Lexer::getObj(Object *obj) {
while ((c = lookChar()) != EOF && !specialChars[c]) {
getChar();
if (++n == tokBufSize) {
- error(getPos(), "Command token too long");
+ error(errSyntaxError, getPos(), "Command token too long");
break;
}
*p++ = c;
diff --git a/xpdf/Link.cc b/xpdf/Link.cc
index ae2de53..56a2963 100644
--- a/xpdf/Link.cc
+++ b/xpdf/Link.cc
@@ -42,7 +42,7 @@ LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
Object obj2, obj3, obj4;
if (!obj->isDict()) {
- error(-1, "Bad annotation action");
+ error(errSyntaxWarning, -1, "Bad annotation action");
return NULL;
}
@@ -92,7 +92,7 @@ LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
// action is missing or wrong type
} else {
- error(-1, "Bad annotation action");
+ error(errSyntaxWarning, -1, "Bad annotation action");
action = NULL;
}
@@ -128,13 +128,13 @@ GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
if (obj1.isString()) {
name = obj1.getString()->copy();
} else {
- error(-1, "Illegal file spec in link");
+ error(errSyntaxWarning, -1, "Illegal file spec in link");
}
obj1.free();
// error
} else {
- error(-1, "Illegal file spec in link");
+ error(errSyntaxWarning, -1, "Illegal file spec in link");
}
// system-dependent path manipulation
@@ -202,7 +202,7 @@ LinkDest::LinkDest(Array *a) {
// get page
if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
return;
}
a->getNF(0, &obj1);
@@ -214,7 +214,7 @@ LinkDest::LinkDest(Array *a) {
pageRef.gen = obj1.getRefGen();
pageIsRef = gTrue;
} else {
- error(-1, "Bad annotation destination");
+ error(errSyntaxWarning, -1, "Bad annotation destination");
goto err2;
}
obj1.free();
@@ -235,7 +235,7 @@ LinkDest::LinkDest(Array *a) {
changeLeft = gTrue;
left = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
goto err1;
}
obj2.free();
@@ -250,7 +250,7 @@ LinkDest::LinkDest(Array *a) {
changeTop = gTrue;
top = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
goto err1;
}
obj2.free();
@@ -265,7 +265,7 @@ LinkDest::LinkDest(Array *a) {
changeZoom = gTrue;
zoom = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
goto err1;
}
obj2.free();
@@ -274,7 +274,7 @@ LinkDest::LinkDest(Array *a) {
// Fit link
} else if (obj1.isName("Fit")) {
if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFit;
@@ -282,58 +282,67 @@ LinkDest::LinkDest(Array *a) {
// FitH link
} else if (obj1.isName("FitH")) {
if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitH;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ if (a->get(2, &obj2)->isNum()) {
+ top = obj2.getNum();
+ changeTop = gTrue;
+ } else if (obj2.isNull()) {
+ changeTop = gFalse;
+ } else {
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
- top = obj2.getNum();
obj2.free();
// FitV link
} else if (obj1.isName("FitV")) {
if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitV;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ if (a->get(2, &obj2)->isNum()) {
+ left = obj2.getNum();
+ changeLeft = gTrue;
+ } else if (obj2.isNull()) {
+ changeLeft = gFalse;
+ } else {
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
- left = obj2.getNum();
obj2.free();
// FitR link
} else if (obj1.isName("FitR")) {
if (a->getLength() < 6) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitR;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ if (a->get(2, &obj2)->isNum()) {
+ left = obj2.getNum();
+ } else {
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
- left = obj2.getNum();
obj2.free();
if (!a->get(3, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
bottom = obj2.getNum();
obj2.free();
if (!a->get(4, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
right = obj2.getNum();
obj2.free();
if (!a->get(5, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
top = obj2.getNum();
@@ -342,7 +351,7 @@ LinkDest::LinkDest(Array *a) {
// FitB link
} else if (obj1.isName("FitB")) {
if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitB;
@@ -350,34 +359,42 @@ LinkDest::LinkDest(Array *a) {
// FitBH link
} else if (obj1.isName("FitBH")) {
if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitBH;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ if (a->get(2, &obj2)->isNum()) {
+ top = obj2.getNum();
+ changeTop = gTrue;
+ } else if (obj2.isNull()) {
+ changeTop = gFalse;
+ } else {
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
- top = obj2.getNum();
obj2.free();
// FitBV link
} else if (obj1.isName("FitBV")) {
if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
+ error(errSyntaxWarning, -1, "Annotation destination array is too short");
goto err2;
}
kind = destFitBV;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
+ if (a->get(2, &obj2)->isNum()) {
+ left = obj2.getNum();
+ changeLeft = gTrue;
+ } else if (obj2.isNull()) {
+ changeLeft = gFalse;
+ } else {
+ error(errSyntaxWarning, -1, "Bad annotation destination position");
kind = destFit;
}
- left = obj2.getNum();
obj2.free();
// unknown link kind
} else {
- error(-1, "Unknown annotation destination type");
+ error(errSyntaxWarning, -1, "Unknown annotation destination type");
goto err2;
}
@@ -433,7 +450,7 @@ LinkGoTo::LinkGoTo(Object *destObj) {
// error
} else {
- error(-1, "Illegal annotation destination");
+ error(errSyntaxWarning, -1, "Illegal annotation destination");
}
}
@@ -471,7 +488,7 @@ LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
// error
} else {
- error(-1, "Illegal annotation destination");
+ error(errSyntaxWarning, -1, "Illegal annotation destination");
}
}
@@ -510,7 +527,7 @@ LinkLaunch::LinkLaunch(Object *actionObj) {
}
obj2.free();
} else {
- error(-1, "Bad launch-type link action");
+ error(errSyntaxWarning, -1, "Bad launch-type link action");
}
#else
//~ This hasn't been defined by Adobe yet, so assume it looks
@@ -524,7 +541,7 @@ LinkLaunch::LinkLaunch(Object *actionObj) {
}
obj2.free();
} else {
- error(-1, "Bad launch-type link action");
+ error(errSyntaxWarning, -1, "Bad launch-type link action");
}
#endif
}
@@ -550,31 +567,34 @@ LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
uri = NULL;
if (uriObj->isString()) {
- uri2 = uriObj->getString()->copy();
- if (baseURI && baseURI->getLength() > 0) {
- n = strcspn(uri2->getCString(), "/:");
- if (n == uri2->getLength() || uri2->getChar(n) == '/') {
+ uri2 = uriObj->getString();
+ n = (int)strcspn(uri2->getCString(), "/:");
+ if (n < uri2->getLength() && uri2->getChar(n) == ':') {
+ // "http:..." etc.
+ uri = uri2->copy();
+ } else if (!uri2->cmpN("www.", 4)) {
+ // "www.[...]" without the leading "http://"
+ uri = new GString("http://");
+ uri->append(uri2);
+ } else {
+ // relative URI
+ if (baseURI) {
uri = baseURI->copy();
c = uri->getChar(uri->getLength() - 1);
- if (c == '/' || c == '?') {
- if (uri2->getChar(0) == '/') {
- uri2->del(0);
- }
+ if (c != '/' && c != '?') {
+ uri->append('/');
+ }
+ if (uri2->getChar(0) == '/') {
+ uri->append(uri2->getCString() + 1, uri2->getLength() - 1);
} else {
- if (uri2->getChar(0) != '/') {
- uri->append('/');
- }
+ uri->append(uri2);
}
- uri->append(uri2);
- delete uri2;
} else {
- uri = uri2;
+ uri = uri2->copy();
}
- } else {
- uri = uri2;
}
} else {
- error(-1, "Illegal URI-type link");
+ error(errSyntaxWarning, -1, "Illegal URI-type link");
}
}
@@ -612,7 +632,8 @@ LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
} else if (titleObj->isString()) {
title = titleObj->getString()->copy();
} else {
- error(-1, "Movie action is missing both the Annot and T keys");
+ error(errSyntaxError, -1,
+ "Movie action is missing both the Annot and T keys");
}
}
@@ -647,29 +668,29 @@ Link::Link(Dict *dict, GString *baseURI) {
// get rectangle
if (!dict->lookup("Rect", &obj1)->isArray()) {
- error(-1, "Annotation rectangle is wrong type");
+ error(errSyntaxError, -1, "Annotation rectangle is wrong type");
goto err2;
}
if (!obj1.arrayGet(0, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
+ error(errSyntaxError, -1, "Bad annotation rectangle");
goto err1;
}
x1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(1, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
+ error(errSyntaxError, -1, "Bad annotation rectangle");
goto err1;
}
y1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(2, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
+ error(errSyntaxError, -1, "Bad annotation rectangle");
goto err1;
}
x2 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(3, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
+ error(errSyntaxError, -1, "Bad annotation rectangle");
goto err1;
}
y2 = obj2.getNum();
diff --git a/xpdf/Link.h b/xpdf/Link.h
index 698f2c8..55fbfa1 100644
--- a/xpdf/Link.h
+++ b/xpdf/Link.h
@@ -110,8 +110,10 @@ private:
double left, bottom; // position
double right, top;
double zoom; // zoom factor
- GBool changeLeft, changeTop; // for destXYZ links, which position
- GBool changeZoom; // components to change
+ GBool changeLeft, changeTop; // which position components to change:
+ GBool changeZoom; // destXYZ uses all three;
+ // destFitH/BH use changeTop;
+ // destFitV/BV use changeLeft
GBool ok; // set if created successfully
LinkDest(LinkDest *dest);
diff --git a/xpdf/Makefile.in b/xpdf/Makefile.in
index b97cc6e..5b48eff 100644
--- a/xpdf/Makefile.in
+++ b/xpdf/Makefile.in
@@ -74,6 +74,7 @@ CXX_SRC = \
$(srcdir)/Link.cc \
$(srcdir)/NameToCharCode.cc \
$(srcdir)/Object.cc \
+ $(srcdir)/OptionalContent.cc \
$(srcdir)/Outline.cc \
$(srcdir)/OutputDev.cc \
$(srcdir)/PDFCore.cc \
@@ -100,6 +101,7 @@ CXX_SRC = \
$(srcdir)/pdftotext.cc \
$(srcdir)/pdfinfo.cc \
$(srcdir)/pdffonts.cc \
+ $(srcdir)/pdfdetach.cc \
$(srcdir)/pdftoppm.cc \
$(srcdir)/pdfimages.cc \
$(srcdir)/xpdf.cc
@@ -107,10 +109,10 @@ CXX_SRC = \
#------------------------------------------------------------------------
all: xpdf$(EXE) pdftops$(EXE) pdftotext$(EXE) pdfinfo$(EXE) \
- pdffonts$(EXE) pdftoppm$(EXE) pdfimages$(EXE)
+ pdffonts$(EXE) pdfdetach$(EXE) pdftoppm$(EXE) pdfimages$(EXE)
all-no-x: pdftops$(EXE) pdftotext$(EXE) pdfinfo$(EXE) pdffonts$(EXE) \
- pdfimages$(EXE)
+ pdfdetach$(EXE) pdfimages$(EXE)
#------------------------------------------------------------------------
@@ -118,12 +120,12 @@ XPDF_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o Catalog.o \
CharCodeToUnicode.o CMap.o CoreOutputDev.o Decrypt.o Dict.o \
Error.o FontEncodingTables.o Function.o Gfx.o GfxFont.o \
GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
- JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o Outline.o \
- OutputDev.o Page.o Parser.o PDFCore.o PDFDoc.o PDFDocEncoding.o \
- PreScanOutputDev.o PSOutputDev.o PSTokenizer.o SecurityHandler.x.o \
- SplashOutputDev.o Stream.o TextOutputDev.o UnicodeMap.o \
- UnicodeTypeTable.o XPDFApp.o XPDFCore.o XPDFTree.o XPDFViewer.o \
- XpdfPluginAPI.o XRef.o xpdf.o
+ JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFCore.o \
+ PDFDoc.o PDFDocEncoding.o PreScanOutputDev.o PSOutputDev.o \
+ PSTokenizer.o SecurityHandler.o SplashOutputDev.o Stream.o \
+ TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XPDFApp.o \
+ XPDFCore.o XPDFTree.o XPDFViewer.o XpdfPluginAPI.o XRef.o xpdf.o
XPDF_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \
$(XLIBS) $(OTHERLIBS) -lm
@@ -136,11 +138,11 @@ PDFTOPS_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o \
GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
- JPXStream.o Lexer.o Link.o NameToCharCode.o Outline.o Object.o \
- OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o \
- PreScanOutputDev.o PSOutputDev.o PSTokenizer.o SecurityHandler.o \
- SplashOutputDev.o Stream.o UnicodeMap.o XpdfPluginAPI.o XRef.o \
- pdftops.o
+ JPXStream.o Lexer.o Link.o NameToCharCode.o OptionalContent.o \
+ Outline.o Object.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PreScanOutputDev.o PSOutputDev.o PSTokenizer.o \
+ SecurityHandler.o SplashOutputDev.o Stream.o UnicodeMap.o \
+ XpdfPluginAPI.o XRef.o pdftops.o
PDFTOPS_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \
$(OTHERLIBS) -lm
@@ -154,10 +156,11 @@ PDFTOTEXT_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o \
GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
- JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o Outline.o \
- OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o PSTokenizer.o \
- SecurityHandler.o Stream.o TextOutputDev.o UnicodeMap.o \
- UnicodeTypeTable.o XpdfPluginAPI.o XRef.o pdftotext.o
+ JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \
+ TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XpdfPluginAPI.o \
+ XRef.o pdftotext.o
PDFTOTEXT_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm
pdftotext$(EXE): $(PDFTOTEXT_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
@@ -170,10 +173,10 @@ PDFINFO_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o \
GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
- JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o Outline.o \
- OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o PSTokenizer.o \
- SecurityHandler.o Stream.o UnicodeMap.o XpdfPluginAPI.o XRef.o \
- pdfinfo.o
+ JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \
+ UnicodeMap.o XpdfPluginAPI.o XRef.o pdfinfo.o
PDFINFO_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm
pdfinfo$(EXE): $(PDFINFO_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
@@ -186,10 +189,10 @@ PDFFONTS_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o \
GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
- JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o Outline.o \
- OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o PSTokenizer.o \
- SecurityHandler.o Stream.o UnicodeMap.o XpdfPluginAPI.o XRef.o \
- pdffonts.o
+ JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \
+ UnicodeMap.o XpdfPluginAPI.o XRef.o pdffonts.o
PDFFONTS_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm
pdffonts$(EXE): $(PDFFONTS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
@@ -198,14 +201,31 @@ pdffonts$(EXE): $(PDFFONTS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
#------------------------------------------------------------------------
+PDFDETACH_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
+ Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
+ FontEncodingTables.o Function.o Gfx.o GfxFont.o \
+ GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \
+ JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \
+ UnicodeMap.o XpdfPluginAPI.o XRef.o pdfdetach.o
+PDFDETACH_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm
+
+pdfdetach$(EXE): $(PDFDETACH_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfdetach$(EXE) $(PDFDETACH_OBJS) \
+ $(PDFDETACH_LIBS)
+
+#------------------------------------------------------------------------
+
PDFTOPPM_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o GfxState.o \
GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o JPXStream.o \
- Lexer.o Link.o NameToCharCode.o Object.o Outline.o OutputDev.o \
- Page.o Parser.o PDFDoc.o PDFDocEncoding.o PSTokenizer.o \
- SecurityHandler.o SplashOutputDev.o Stream.o TextOutputDev.o \
- UnicodeMap.o UnicodeTypeTable.o XpdfPluginAPI.o XRef.o pdftoppm.o
+ Lexer.o Link.o NameToCharCode.o Object.o OptionalContent.o \
+ Outline.o OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o \
+ PSTokenizer.o SecurityHandler.o SplashOutputDev.o Stream.o \
+ TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XpdfPluginAPI.o \
+ XRef.o pdftoppm.o
PDFTOPPM_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \
$(OTHERLIBS) -lm
@@ -220,9 +240,9 @@ PDFIMAGES_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \
FontEncodingTables.o Function.o Gfx.o GfxFont.o GfxState.o \
GlobalParams.o ImageOutputDev.o JArithmeticDecoder.o \
JBIG2Stream.o JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \
- Outline.o OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o \
- PSTokenizer.o SecurityHandler.o Stream.o UnicodeMap.o \
- XpdfPluginAPI.o XRef.o pdfimages.o
+ OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \
+ PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \
+ UnicodeMap.o XpdfPluginAPI.o XRef.o pdfimages.o
PDFIMAGES_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm
pdfimages$(EXE): $(PDFIMAGES_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
@@ -231,18 +251,13 @@ pdfimages$(EXE): $(PDFIMAGES_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a
#------------------------------------------------------------------------
-SecurityHandler.x.o: SecurityHandler.cc
- $(CXX) $(CXXFLAGS) -DHAVE_XPDFCORE -c -o SecurityHandler.x.o \
- SecurityHandler.cc
-
-#------------------------------------------------------------------------
-
clean:
rm -f $(XPDF_OBJS) xpdf$(EXE)
rm -f $(PDFTOPS_OBJS) pdftops$(EXE)
rm -f $(PDFTOTEXT_OBJS) pdftotext$(EXE)
rm -f $(PDFINFO_OBJS) pdfinfo$(EXE)
rm -f $(PDFFONTS_OBJS) pdffonts$(EXE)
+ rm -f $(PDFDETACH_OBJS) pdfdetach$(EXE)
rm -f $(PDFTOPPM_OBJS) pdftoppm$(EXE)
rm -f $(PDFIMAGES_OBJS) pdfimages$(EXE)
diff --git a/xpdf/NameToCharCode.cc b/xpdf/NameToCharCode.cc
index 7ebf4e1..c05fdf5 100644
--- a/xpdf/NameToCharCode.cc
+++ b/xpdf/NameToCharCode.cc
@@ -47,7 +47,7 @@ NameToCharCode::~NameToCharCode() {
gfree(tab);
}
-void NameToCharCode::add(char *name, CharCode c) {
+void NameToCharCode::add(const char *name, CharCode c) {
NameToCharCodeEntry *oldTab;
int h, i, oldSize;
@@ -89,7 +89,7 @@ void NameToCharCode::add(char *name, CharCode c) {
++len;
}
-CharCode NameToCharCode::lookup(char *name) {
+CharCode NameToCharCode::lookup(const char *name) {
int h;
h = hash(name);
@@ -104,8 +104,8 @@ CharCode NameToCharCode::lookup(char *name) {
return 0;
}
-int NameToCharCode::hash(char *name) {
- char *p;
+int NameToCharCode::hash(const char *name) {
+ const char *p;
unsigned int h;
h = 0;
diff --git a/xpdf/NameToCharCode.h b/xpdf/NameToCharCode.h
index 65453c3..6548133 100644
--- a/xpdf/NameToCharCode.h
+++ b/xpdf/NameToCharCode.h
@@ -27,12 +27,12 @@ public:
NameToCharCode();
~NameToCharCode();
- void add(char *name, CharCode c);
- CharCode lookup(char *name);
+ void add(const char *name, CharCode c);
+ CharCode lookup(const char *name);
private:
- int hash(char *name);
+ int hash(const char *name);
NameToCharCodeEntry *tab;
int size;
diff --git a/xpdf/NameToUnicodeTable.h b/xpdf/NameToUnicodeTable.h
index c5ecba4..c516dea 100644
--- a/xpdf/NameToUnicodeTable.h
+++ b/xpdf/NameToUnicodeTable.h
@@ -8,7 +8,7 @@
static struct {
Unicode u;
- char *name;
+ const char *name;
} nameToUnicodeTab[] = {
{0x0021, "!"},
{0x0023, "#"},
@@ -44,146 +44,392 @@ static struct {
{0x0041, "A"},
{0x00c6, "AE"},
{0x01fc, "AEacute"},
+ {0x01e2, "AEmacron"},
{0xf7e6, "AEsmall"},
{0x00c1, "Aacute"},
{0xf7e1, "Aacutesmall"},
{0x0102, "Abreve"},
+ {0x1eae, "Abreveacute"},
+ {0x04d0, "Abrevecyrillic"},
+ {0x1eb6, "Abrevedotbelow"},
+ {0x1eb0, "Abrevegrave"},
+ {0x1eb2, "Abrevehookabove"},
+ {0x1eb4, "Abrevetilde"},
+ {0x01cd, "Acaron"},
+ {0x24b6, "Acircle"},
{0x00c2, "Acircumflex"},
+ {0x1ea4, "Acircumflexacute"},
+ {0x1eac, "Acircumflexdotbelow"},
+ {0x1ea6, "Acircumflexgrave"},
+ {0x1ea8, "Acircumflexhookabove"},
{0xf7e2, "Acircumflexsmall"},
+ {0x1eaa, "Acircumflextilde"},
{0xf6c9, "Acute"},
{0xf7b4, "Acutesmall"},
+ {0x0410, "Acyrillic"},
+ {0x0200, "Adblgrave"},
{0x00c4, "Adieresis"},
+ {0x04d2, "Adieresiscyrillic"},
+ {0x01de, "Adieresismacron"},
{0xf7e4, "Adieresissmall"},
+ {0x1ea0, "Adotbelow"},
+ {0x01e0, "Adotmacron"},
{0x00c0, "Agrave"},
{0xf7e0, "Agravesmall"},
+ {0x1ea2, "Ahookabove"},
+ {0x04d4, "Aiecyrillic"},
+ {0x0202, "Ainvertedbreve"},
{0x0391, "Alpha"},
{0x0386, "Alphatonos"},
{0x0100, "Amacron"},
+ {0xff21, "Amonospace"},
{0x0104, "Aogonek"},
{0x00c5, "Aring"},
{0x01fa, "Aringacute"},
+ {0x1e00, "Aringbelow"},
{0xf7e5, "Aringsmall"},
{0xf761, "Asmall"},
{0x00c3, "Atilde"},
{0xf7e3, "Atildesmall"},
+ {0x0531, "Aybarmenian"},
{0x0042, "B"},
+ {0x24b7, "Bcircle"},
+ {0x1e02, "Bdotaccent"},
+ {0x1e04, "Bdotbelow"},
+ {0x0411, "Becyrillic"},
+ {0x0532, "Benarmenian"},
{0x0392, "Beta"},
+ {0x0181, "Bhook"},
+ {0x1e06, "Blinebelow"},
+ {0xff22, "Bmonospace"},
{0xf6f4, "Brevesmall"},
{0xf762, "Bsmall"},
+ {0x0182, "Btopbar"},
{0x0043, "C"},
+ {0x053e, "Caarmenian"},
{0x0106, "Cacute"},
{0xf6ca, "Caron"},
{0xf6f5, "Caronsmall"},
{0x010c, "Ccaron"},
{0x00c7, "Ccedilla"},
+ {0x1e08, "Ccedillaacute"},
{0xf7e7, "Ccedillasmall"},
+ {0x24b8, "Ccircle"},
{0x0108, "Ccircumflex"},
+ {0x010a, "Cdot"},
{0x010a, "Cdotaccent"},
{0xf7b8, "Cedillasmall"},
+ {0x0549, "Chaarmenian"},
+ {0x04bc, "Cheabkhasiancyrillic"},
+ {0x0427, "Checyrillic"},
+ {0x04be, "Chedescenderabkhasiancyrillic"},
+ {0x04b6, "Chedescendercyrillic"},
+ {0x04f4, "Chedieresiscyrillic"},
+ {0x0543, "Cheharmenian"},
+ {0x04cb, "Chekhakassiancyrillic"},
+ {0x04b8, "Cheverticalstrokecyrillic"},
{0x03a7, "Chi"},
+ {0x0187, "Chook"},
{0xf6f6, "Circumflexsmall"},
+ {0xff23, "Cmonospace"},
+ {0x0551, "Coarmenian"},
{0xf763, "Csmall"},
{0x0044, "D"},
+ {0x01f1, "DZ"},
+ {0x01c4, "DZcaron"},
+ {0x0534, "Daarmenian"},
+ {0x0189, "Dafrican"},
{0x010e, "Dcaron"},
+ {0x1e10, "Dcedilla"},
+ {0x24b9, "Dcircle"},
+ {0x1e12, "Dcircumflexbelow"},
{0x0110, "Dcroat"},
+ {0x1e0a, "Ddotaccent"},
+ {0x1e0c, "Ddotbelow"},
+ {0x0414, "Decyrillic"},
+ {0x03ee, "Deicoptic"},
{0x2206, "Delta"},
+ {0x0394, "Deltagreek"},
+ {0x018a, "Dhook"},
{0xf6cb, "Dieresis"},
{0xf6cc, "DieresisAcute"},
{0xf6cd, "DieresisGrave"},
{0xf7a8, "Dieresissmall"},
+ {0x03dc, "Digammagreek"},
+ {0x0402, "Djecyrillic"},
+ {0x1e0e, "Dlinebelow"},
+ {0xff24, "Dmonospace"},
{0xf6f7, "Dotaccentsmall"},
+ {0x0110, "Dslash"},
{0xf764, "Dsmall"},
+ {0x018b, "Dtopbar"},
+ {0x01f2, "Dz"},
+ {0x01c5, "Dzcaron"},
+ {0x04e0, "Dzeabkhasiancyrillic"},
+ {0x0405, "Dzecyrillic"},
+ {0x040f, "Dzhecyrillic"},
{0x0045, "E"},
{0x00c9, "Eacute"},
{0xf7e9, "Eacutesmall"},
{0x0114, "Ebreve"},
{0x011a, "Ecaron"},
+ {0x1e1c, "Ecedillabreve"},
+ {0x0535, "Echarmenian"},
+ {0x24ba, "Ecircle"},
{0x00ca, "Ecircumflex"},
+ {0x1ebe, "Ecircumflexacute"},
+ {0x1e18, "Ecircumflexbelow"},
+ {0x1ec6, "Ecircumflexdotbelow"},
+ {0x1ec0, "Ecircumflexgrave"},
+ {0x1ec2, "Ecircumflexhookabove"},
{0xf7ea, "Ecircumflexsmall"},
+ {0x1ec4, "Ecircumflextilde"},
+ {0x0404, "Ecyrillic"},
+ {0x0204, "Edblgrave"},
{0x00cb, "Edieresis"},
{0xf7eb, "Edieresissmall"},
+ {0x0116, "Edot"},
{0x0116, "Edotaccent"},
+ {0x1eb8, "Edotbelow"},
+ {0x0424, "Efcyrillic"},
{0x00c8, "Egrave"},
{0xf7e8, "Egravesmall"},
+ {0x0537, "Eharmenian"},
+ {0x1eba, "Ehookabove"},
+ {0x2167, "Eightroman"},
+ {0x0206, "Einvertedbreve"},
+ {0x0464, "Eiotifiedcyrillic"},
+ {0x041b, "Elcyrillic"},
+ {0x216a, "Elevenroman"},
{0x0112, "Emacron"},
+ {0x1e16, "Emacronacute"},
+ {0x1e14, "Emacrongrave"},
+ {0x041c, "Emcyrillic"},
+ {0xff25, "Emonospace"},
+ {0x041d, "Encyrillic"},
+ {0x04a2, "Endescendercyrillic"},
{0x014a, "Eng"},
+ {0x04a4, "Enghecyrillic"},
+ {0x04c7, "Enhookcyrillic"},
{0x0118, "Eogonek"},
+ {0x0190, "Eopen"},
{0x0395, "Epsilon"},
{0x0388, "Epsilontonos"},
+ {0x0420, "Ercyrillic"},
+ {0x018e, "Ereversed"},
+ {0x042d, "Ereversedcyrillic"},
+ {0x0421, "Escyrillic"},
+ {0x04aa, "Esdescendercyrillic"},
+ {0x01a9, "Esh"},
{0xf765, "Esmall"},
{0x0397, "Eta"},
+ {0x0538, "Etarmenian"},
{0x0389, "Etatonos"},
{0x00d0, "Eth"},
{0xf7f0, "Ethsmall"},
+ {0x1ebc, "Etilde"},
+ {0x1e1a, "Etildebelow"},
{0x20ac, "Euro"},
+ {0x01b7, "Ezh"},
+ {0x01ee, "Ezhcaron"},
+ {0x01b8, "Ezhreversed"},
{0x0046, "F"},
+ {0x24bb, "Fcircle"},
+ {0x1e1e, "Fdotaccent"},
+ {0x0556, "Feharmenian"},
+ {0x03e4, "Feicoptic"},
+ {0x0191, "Fhook"},
+ {0x0472, "Fitacyrillic"},
+ {0x2164, "Fiveroman"},
+ {0xff26, "Fmonospace"},
+ {0x2163, "Fourroman"},
{0xf766, "Fsmall"},
{0x0047, "G"},
+ {0x3387, "GBsquare"},
+ {0x01f4, "Gacute"},
{0x0393, "Gamma"},
+ {0x0194, "Gammaafrican"},
+ {0x03ea, "Gangiacoptic"},
{0x011e, "Gbreve"},
{0x01e6, "Gcaron"},
+ {0x0122, "Gcedilla"},
+ {0x24bc, "Gcircle"},
{0x011c, "Gcircumflex"},
{0x0122, "Gcommaaccent"},
+ {0x0120, "Gdot"},
{0x0120, "Gdotaccent"},
+ {0x0413, "Gecyrillic"},
+ {0x0542, "Ghadarmenian"},
+ {0x0494, "Ghemiddlehookcyrillic"},
+ {0x0492, "Ghestrokecyrillic"},
+ {0x0490, "Gheupturncyrillic"},
+ {0x0193, "Ghook"},
+ {0x0533, "Gimarmenian"},
+ {0x0403, "Gjecyrillic"},
+ {0x1e20, "Gmacron"},
+ {0xff27, "Gmonospace"},
{0xf6ce, "Grave"},
{0xf760, "Gravesmall"},
{0xf767, "Gsmall"},
+ {0x029b, "Gsmallhook"},
+ {0x01e4, "Gstroke"},
{0x0048, "H"},
{0x25cf, "H18533"},
{0x25aa, "H18543"},
{0x25ab, "H18551"},
{0x25a1, "H22073"},
+ {0x33cb, "HPsquare"},
+ {0x04a8, "Haabkhasiancyrillic"},
+ {0x04b2, "Hadescendercyrillic"},
+ {0x042a, "Hardsigncyrillic"},
{0x0126, "Hbar"},
+ {0x1e2a, "Hbrevebelow"},
+ {0x1e28, "Hcedilla"},
+ {0x24bd, "Hcircle"},
{0x0124, "Hcircumflex"},
+ {0x1e26, "Hdieresis"},
+ {0x1e22, "Hdotaccent"},
+ {0x1e24, "Hdotbelow"},
+ {0xff28, "Hmonospace"},
+ {0x0540, "Hoarmenian"},
+ {0x03e8, "Horicoptic"},
{0xf768, "Hsmall"},
{0xf6cf, "Hungarumlaut"},
{0xf6f8, "Hungarumlautsmall"},
+ {0x3390, "Hzsquare"},
{0x0049, "I"},
+ {0x042f, "IAcyrillic"},
{0x0132, "IJ"},
+ {0x042e, "IUcyrillic"},
{0x00cd, "Iacute"},
{0xf7ed, "Iacutesmall"},
{0x012c, "Ibreve"},
+ {0x01cf, "Icaron"},
+ {0x24be, "Icircle"},
{0x00ce, "Icircumflex"},
{0xf7ee, "Icircumflexsmall"},
+ {0x0406, "Icyrillic"},
+ {0x0208, "Idblgrave"},
{0x00cf, "Idieresis"},
+ {0x1e2e, "Idieresisacute"},
+ {0x04e4, "Idieresiscyrillic"},
{0xf7ef, "Idieresissmall"},
+ {0x0130, "Idot"},
{0x0130, "Idotaccent"},
+ {0x1eca, "Idotbelow"},
+ {0x04d6, "Iebrevecyrillic"},
+ {0x0415, "Iecyrillic"},
{0x2111, "Ifraktur"},
{0x00cc, "Igrave"},
{0xf7ec, "Igravesmall"},
+ {0x1ec8, "Ihookabove"},
+ {0x0418, "Iicyrillic"},
+ {0x020a, "Iinvertedbreve"},
+ {0x0419, "Iishortcyrillic"},
{0x012a, "Imacron"},
+ {0x04e2, "Imacroncyrillic"},
+ {0xff29, "Imonospace"},
+ {0x053b, "Iniarmenian"},
+ {0x0401, "Iocyrillic"},
{0x012e, "Iogonek"},
{0x0399, "Iota"},
+ {0x0196, "Iotaafrican"},
{0x03aa, "Iotadieresis"},
{0x038a, "Iotatonos"},
{0xf769, "Ismall"},
+ {0x0197, "Istroke"},
{0x0128, "Itilde"},
+ {0x1e2c, "Itildebelow"},
+ {0x0474, "Izhitsacyrillic"},
+ {0x0476, "Izhitsadblgravecyrillic"},
{0x004a, "J"},
+ {0x0541, "Jaarmenian"},
+ {0x24bf, "Jcircle"},
{0x0134, "Jcircumflex"},
+ {0x0408, "Jecyrillic"},
+ {0x054b, "Jheharmenian"},
+ {0xff2a, "Jmonospace"},
{0xf76a, "Jsmall"},
{0x004b, "K"},
+ {0x3385, "KBsquare"},
+ {0x33cd, "KKsquare"},
+ {0x04a0, "Kabashkircyrillic"},
+ {0x1e30, "Kacute"},
+ {0x041a, "Kacyrillic"},
+ {0x049a, "Kadescendercyrillic"},
+ {0x04c3, "Kahookcyrillic"},
{0x039a, "Kappa"},
+ {0x049e, "Kastrokecyrillic"},
+ {0x049c, "Kaverticalstrokecyrillic"},
+ {0x01e8, "Kcaron"},
+ {0x0136, "Kcedilla"},
+ {0x24c0, "Kcircle"},
{0x0136, "Kcommaaccent"},
+ {0x1e32, "Kdotbelow"},
+ {0x0554, "Keharmenian"},
+ {0x053f, "Kenarmenian"},
+ {0x0425, "Khacyrillic"},
+ {0x03e6, "Kheicoptic"},
+ {0x0198, "Khook"},
+ {0x040c, "Kjecyrillic"},
+ {0x1e34, "Klinebelow"},
+ {0xff2b, "Kmonospace"},
+ {0x0480, "Koppacyrillic"},
+ {0x03de, "Koppagreek"},
+ {0x046e, "Ksicyrillic"},
{0xf76b, "Ksmall"},
{0x004c, "L"},
+ {0x01c7, "LJ"},
{0xf6bf, "LL"},
{0x0139, "Lacute"},
{0x039b, "Lambda"},
{0x013d, "Lcaron"},
+ {0x013b, "Lcedilla"},
+ {0x24c1, "Lcircle"},
+ {0x1e3c, "Lcircumflexbelow"},
{0x013b, "Lcommaaccent"},
{0x013f, "Ldot"},
+ {0x013f, "Ldotaccent"},
+ {0x1e36, "Ldotbelow"},
+ {0x1e38, "Ldotbelowmacron"},
+ {0x053c, "Liwnarmenian"},
+ {0x01c8, "Lj"},
+ {0x0409, "Ljecyrillic"},
+ {0x1e3a, "Llinebelow"},
+ {0xff2c, "Lmonospace"},
{0x0141, "Lslash"},
{0xf6f9, "Lslashsmall"},
{0xf76c, "Lsmall"},
{0x004d, "M"},
+ {0x3386, "MBsquare"},
{0xf6d0, "Macron"},
{0xf7af, "Macronsmall"},
+ {0x1e3e, "Macute"},
+ {0x24c2, "Mcircle"},
+ {0x1e40, "Mdotaccent"},
+ {0x1e42, "Mdotbelow"},
+ {0x0544, "Menarmenian"},
+ {0xff2d, "Mmonospace"},
{0xf76d, "Msmall"},
+ {0x019c, "Mturned"},
{0x039c, "Mu"},
{0x004e, "N"},
+ {0x01ca, "NJ"},
{0x0143, "Nacute"},
{0x0147, "Ncaron"},
+ {0x0145, "Ncedilla"},
+ {0x24c3, "Ncircle"},
+ {0x1e4a, "Ncircumflexbelow"},
{0x0145, "Ncommaaccent"},
+ {0x1e44, "Ndotaccent"},
+ {0x1e46, "Ndotbelow"},
+ {0x019d, "Nhookleft"},
+ {0x2168, "Nineroman"},
+ {0x01cb, "Nj"},
+ {0x040a, "Njecyrillic"},
+ {0x1e48, "Nlinebelow"},
+ {0xff2e, "Nmonospace"},
+ {0x0546, "Nowarmenian"},
{0xf76e, "Nsmall"},
{0x00d1, "Ntilde"},
{0xf7f1, "Ntildesmall"},
@@ -193,42 +439,107 @@ static struct {
{0xf6fa, "OEsmall"},
{0x00d3, "Oacute"},
{0xf7f3, "Oacutesmall"},
+ {0x04e8, "Obarredcyrillic"},
+ {0x04ea, "Obarreddieresiscyrillic"},
{0x014e, "Obreve"},
+ {0x01d1, "Ocaron"},
+ {0x019f, "Ocenteredtilde"},
+ {0x24c4, "Ocircle"},
{0x00d4, "Ocircumflex"},
+ {0x1ed0, "Ocircumflexacute"},
+ {0x1ed8, "Ocircumflexdotbelow"},
+ {0x1ed2, "Ocircumflexgrave"},
+ {0x1ed4, "Ocircumflexhookabove"},
{0xf7f4, "Ocircumflexsmall"},
+ {0x1ed6, "Ocircumflextilde"},
+ {0x041e, "Ocyrillic"},
+ {0x0150, "Odblacute"},
+ {0x020c, "Odblgrave"},
{0x00d6, "Odieresis"},
+ {0x04e6, "Odieresiscyrillic"},
{0xf7f6, "Odieresissmall"},
+ {0x1ecc, "Odotbelow"},
{0xf6fb, "Ogoneksmall"},
{0x00d2, "Ograve"},
{0xf7f2, "Ogravesmall"},
+ {0x0555, "Oharmenian"},
+ {0x2126, "Ohm"},
+ {0x1ece, "Ohookabove"},
{0x01a0, "Ohorn"},
+ {0x1eda, "Ohornacute"},
+ {0x1ee2, "Ohorndotbelow"},
+ {0x1edc, "Ohorngrave"},
+ {0x1ede, "Ohornhookabove"},
+ {0x1ee0, "Ohorntilde"},
{0x0150, "Ohungarumlaut"},
+ {0x01a2, "Oi"},
+ {0x020e, "Oinvertedbreve"},
{0x014c, "Omacron"},
+ {0x1e52, "Omacronacute"},
+ {0x1e50, "Omacrongrave"},
{0x2126, "Omega"},
+ {0x0460, "Omegacyrillic"},
+ {0x03a9, "Omegagreek"},
+ {0x047a, "Omegaroundcyrillic"},
+ {0x047c, "Omegatitlocyrillic"},
{0x038f, "Omegatonos"},
{0x039f, "Omicron"},
{0x038c, "Omicrontonos"},
+ {0xff2f, "Omonospace"},
+ {0x2160, "Oneroman"},
+ {0x01ea, "Oogonek"},
+ {0x01ec, "Oogonekmacron"},
+ {0x0186, "Oopen"},
{0x00d8, "Oslash"},
{0x01fe, "Oslashacute"},
{0xf7f8, "Oslashsmall"},
{0xf76f, "Osmall"},
+ {0x01fe, "Ostrokeacute"},
+ {0x047e, "Otcyrillic"},
{0x00d5, "Otilde"},
+ {0x1e4c, "Otildeacute"},
+ {0x1e4e, "Otildedieresis"},
{0xf7f5, "Otildesmall"},
{0x0050, "P"},
+ {0x1e54, "Pacute"},
+ {0x24c5, "Pcircle"},
+ {0x1e56, "Pdotaccent"},
+ {0x041f, "Pecyrillic"},
+ {0x054a, "Peharmenian"},
+ {0x04a6, "Pemiddlehookcyrillic"},
{0x03a6, "Phi"},
+ {0x01a4, "Phook"},
{0x03a0, "Pi"},
+ {0x0553, "Piwrarmenian"},
+ {0xff30, "Pmonospace"},
{0x03a8, "Psi"},
+ {0x0470, "Psicyrillic"},
{0xf770, "Psmall"},
{0x0051, "Q"},
+ {0x24c6, "Qcircle"},
+ {0xff31, "Qmonospace"},
{0xf771, "Qsmall"},
{0x0052, "R"},
+ {0x054c, "Raarmenian"},
{0x0154, "Racute"},
{0x0158, "Rcaron"},
+ {0x0156, "Rcedilla"},
+ {0x24c7, "Rcircle"},
{0x0156, "Rcommaaccent"},
+ {0x0210, "Rdblgrave"},
+ {0x1e58, "Rdotaccent"},
+ {0x1e5a, "Rdotbelow"},
+ {0x1e5c, "Rdotbelowmacron"},
+ {0x0550, "Reharmenian"},
{0x211c, "Rfraktur"},
{0x03a1, "Rho"},
{0xf6fc, "Ringsmall"},
+ {0x0212, "Rinvertedbreve"},
+ {0x1e5e, "Rlinebelow"},
+ {0xff32, "Rmonospace"},
{0xf772, "Rsmall"},
+ {0x0281, "Rsmallinverted"},
+ {0x02b6, "Rsmallinvertedsuperior"},
{0x0053, "S"},
{0x250c, "SF010000"},
{0x2514, "SF020000"},
@@ -271,70 +582,199 @@ static struct {
{0x256b, "SF530000"},
{0x256a, "SF540000"},
{0x015a, "Sacute"},
+ {0x1e64, "Sacutedotaccent"},
+ {0x03e0, "Sampigreek"},
{0x0160, "Scaron"},
+ {0x1e66, "Scarondotaccent"},
{0xf6fd, "Scaronsmall"},
{0x015e, "Scedilla"},
+ {0x018f, "Schwa"},
+ {0x04d8, "Schwacyrillic"},
+ {0x04da, "Schwadieresiscyrillic"},
+ {0x24c8, "Scircle"},
{0x015c, "Scircumflex"},
{0x0218, "Scommaaccent"},
+ {0x1e60, "Sdotaccent"},
+ {0x1e62, "Sdotbelow"},
+ {0x1e68, "Sdotbelowdotaccent"},
+ {0x054d, "Seharmenian"},
+ {0x2166, "Sevenroman"},
+ {0x0547, "Shaarmenian"},
+ {0x0428, "Shacyrillic"},
+ {0x0429, "Shchacyrillic"},
+ {0x03e2, "Sheicoptic"},
+ {0x04ba, "Shhacyrillic"},
+ {0x03ec, "Shimacoptic"},
{0x03a3, "Sigma"},
+ {0x2165, "Sixroman"},
+ {0xff33, "Smonospace"},
+ {0x042c, "Softsigncyrillic"},
{0xf773, "Ssmall"},
+ {0x03da, "Stigmagreek"},
{0x0054, "T"},
{0x03a4, "Tau"},
{0x0166, "Tbar"},
{0x0164, "Tcaron"},
+ {0x0162, "Tcedilla"},
+ {0x24c9, "Tcircle"},
+ {0x1e70, "Tcircumflexbelow"},
{0x0162, "Tcommaaccent"},
+ {0x1e6a, "Tdotaccent"},
+ {0x1e6c, "Tdotbelow"},
+ {0x0422, "Tecyrillic"},
+ {0x04ac, "Tedescendercyrillic"},
+ {0x2169, "Tenroman"},
+ {0x04b4, "Tetsecyrillic"},
{0x0398, "Theta"},
+ {0x01ac, "Thook"},
{0x00de, "Thorn"},
{0xf7fe, "Thornsmall"},
+ {0x2162, "Threeroman"},
{0xf6fe, "Tildesmall"},
+ {0x054f, "Tiwnarmenian"},
+ {0x1e6e, "Tlinebelow"},
+ {0xff34, "Tmonospace"},
+ {0x0539, "Toarmenian"},
+ {0x01bc, "Tonefive"},
+ {0x0184, "Tonesix"},
+ {0x01a7, "Tonetwo"},
+ {0x01ae, "Tretroflexhook"},
+ {0x0426, "Tsecyrillic"},
+ {0x040b, "Tshecyrillic"},
{0xf774, "Tsmall"},
+ {0x216b, "Twelveroman"},
+ {0x2161, "Tworoman"},
{0x0055, "U"},
{0x00da, "Uacute"},
{0xf7fa, "Uacutesmall"},
{0x016c, "Ubreve"},
+ {0x01d3, "Ucaron"},
+ {0x24ca, "Ucircle"},
{0x00db, "Ucircumflex"},
+ {0x1e76, "Ucircumflexbelow"},
{0xf7fb, "Ucircumflexsmall"},
+ {0x0423, "Ucyrillic"},
+ {0x0170, "Udblacute"},
+ {0x0214, "Udblgrave"},
{0x00dc, "Udieresis"},
+ {0x01d7, "Udieresisacute"},
+ {0x1e72, "Udieresisbelow"},
+ {0x01d9, "Udieresiscaron"},
+ {0x04f0, "Udieresiscyrillic"},
+ {0x01db, "Udieresisgrave"},
+ {0x01d5, "Udieresismacron"},
{0xf7fc, "Udieresissmall"},
+ {0x1ee4, "Udotbelow"},
{0x00d9, "Ugrave"},
{0xf7f9, "Ugravesmall"},
+ {0x1ee6, "Uhookabove"},
{0x01af, "Uhorn"},
+ {0x1ee8, "Uhornacute"},
+ {0x1ef0, "Uhorndotbelow"},
+ {0x1eea, "Uhorngrave"},
+ {0x1eec, "Uhornhookabove"},
+ {0x1eee, "Uhorntilde"},
{0x0170, "Uhungarumlaut"},
+ {0x04f2, "Uhungarumlautcyrillic"},
+ {0x0216, "Uinvertedbreve"},
+ {0x0478, "Ukcyrillic"},
{0x016a, "Umacron"},
+ {0x04ee, "Umacroncyrillic"},
+ {0x1e7a, "Umacrondieresis"},
+ {0xff35, "Umonospace"},
{0x0172, "Uogonek"},
{0x03a5, "Upsilon"},
{0x03d2, "Upsilon1"},
+ {0x03d3, "Upsilonacutehooksymbolgreek"},
+ {0x01b1, "Upsilonafrican"},
{0x03ab, "Upsilondieresis"},
+ {0x03d4, "Upsilondieresishooksymbolgreek"},
+ {0x03d2, "Upsilonhooksymbol"},
{0x038e, "Upsilontonos"},
{0x016e, "Uring"},
+ {0x040e, "Ushortcyrillic"},
{0xf775, "Usmall"},
+ {0x04ae, "Ustraightcyrillic"},
+ {0x04b0, "Ustraightstrokecyrillic"},
{0x0168, "Utilde"},
+ {0x1e78, "Utildeacute"},
+ {0x1e74, "Utildebelow"},
{0x0056, "V"},
+ {0x24cb, "Vcircle"},
+ {0x1e7e, "Vdotbelow"},
+ {0x0412, "Vecyrillic"},
+ {0x054e, "Vewarmenian"},
+ {0x01b2, "Vhook"},
+ {0xff36, "Vmonospace"},
+ {0x0548, "Voarmenian"},
{0xf776, "Vsmall"},
+ {0x1e7c, "Vtilde"},
{0x0057, "W"},
{0x1e82, "Wacute"},
+ {0x24cc, "Wcircle"},
{0x0174, "Wcircumflex"},
{0x1e84, "Wdieresis"},
+ {0x1e86, "Wdotaccent"},
+ {0x1e88, "Wdotbelow"},
{0x1e80, "Wgrave"},
+ {0xff37, "Wmonospace"},
{0xf777, "Wsmall"},
{0x0058, "X"},
+ {0x24cd, "Xcircle"},
+ {0x1e8c, "Xdieresis"},
+ {0x1e8a, "Xdotaccent"},
+ {0x053d, "Xeharmenian"},
{0x039e, "Xi"},
+ {0xff38, "Xmonospace"},
{0xf778, "Xsmall"},
{0x0059, "Y"},
{0x00dd, "Yacute"},
{0xf7fd, "Yacutesmall"},
+ {0x0462, "Yatcyrillic"},
+ {0x24ce, "Ycircle"},
{0x0176, "Ycircumflex"},
{0x0178, "Ydieresis"},
{0xf7ff, "Ydieresissmall"},
+ {0x1e8e, "Ydotaccent"},
+ {0x1ef4, "Ydotbelow"},
+ {0x042b, "Yericyrillic"},
+ {0x04f8, "Yerudieresiscyrillic"},
{0x1ef2, "Ygrave"},
+ {0x01b3, "Yhook"},
+ {0x1ef6, "Yhookabove"},
+ {0x0545, "Yiarmenian"},
+ {0x0407, "Yicyrillic"},
+ {0x0552, "Yiwnarmenian"},
+ {0xff39, "Ymonospace"},
{0xf779, "Ysmall"},
+ {0x1ef8, "Ytilde"},
+ {0x046a, "Yusbigcyrillic"},
+ {0x046c, "Yusbigiotifiedcyrillic"},
+ {0x0466, "Yuslittlecyrillic"},
+ {0x0468, "Yuslittleiotifiedcyrillic"},
{0x005a, "Z"},
+ {0x0536, "Zaarmenian"},
{0x0179, "Zacute"},
{0x017d, "Zcaron"},
{0xf6ff, "Zcaronsmall"},
+ {0x24cf, "Zcircle"},
+ {0x1e90, "Zcircumflex"},
+ {0x017b, "Zdot"},
{0x017b, "Zdotaccent"},
+ {0x1e92, "Zdotbelow"},
+ {0x0417, "Zecyrillic"},
+ {0x0498, "Zedescendercyrillic"},
+ {0x04de, "Zedieresiscyrillic"},
{0x0396, "Zeta"},
+ {0x053a, "Zhearmenian"},
+ {0x04c1, "Zhebrevecyrillic"},
+ {0x0416, "Zhecyrillic"},
+ {0x0496, "Zhedescendercyrillic"},
+ {0x04dc, "Zhedieresiscyrillic"},
+ {0x1e94, "Zlinebelow"},
+ {0xff3a, "Zmonospace"},
{0xf77a, "Zsmall"},
+ {0x01b5, "Zstroke"},
{0x0022, "\""},
{0x005c, "\\"},
{0x005d, "]"},
@@ -342,15 +782,57 @@ static struct {
{0x005f, "_"},
{0x0060, "`"},
{0x0061, "a"},
+ {0x0986, "aabengali"},
{0x00e1, "aacute"},
+ {0x0906, "aadeva"},
+ {0x0a86, "aagujarati"},
+ {0x0a06, "aagurmukhi"},
+ {0x0a3e, "aamatragurmukhi"},
+ {0x3303, "aarusquare"},
+ {0x09be, "aavowelsignbengali"},
+ {0x093e, "aavowelsigndeva"},
+ {0x0abe, "aavowelsigngujarati"},
+ {0x055f, "abbreviationmarkarmenian"},
+ {0x0970, "abbreviationsigndeva"},
+ {0x0985, "abengali"},
+ {0x311a, "abopomofo"},
{0x0103, "abreve"},
+ {0x1eaf, "abreveacute"},
+ {0x04d1, "abrevecyrillic"},
+ {0x1eb7, "abrevedotbelow"},
+ {0x1eb1, "abrevegrave"},
+ {0x1eb3, "abrevehookabove"},
+ {0x1eb5, "abrevetilde"},
+ {0x01ce, "acaron"},
+ {0x24d0, "acircle"},
{0x00e2, "acircumflex"},
+ {0x1ea5, "acircumflexacute"},
+ {0x1ead, "acircumflexdotbelow"},
+ {0x1ea7, "acircumflexgrave"},
+ {0x1ea9, "acircumflexhookabove"},
+ {0x1eab, "acircumflextilde"},
{0x00b4, "acute"},
+ {0x0317, "acutebelowcmb"},
+ {0x0301, "acutecmb"},
{0x0301, "acutecomb"},
+ {0x0954, "acutedeva"},
+ {0x02cf, "acutelowmod"},
+ {0x0341, "acutetonecmb"},
+ {0x0430, "acyrillic"},
+ {0x0201, "adblgrave"},
+ {0x0a71, "addakgurmukhi"},
+ {0x0905, "adeva"},
{0x00e4, "adieresis"},
+ {0x04d3, "adieresiscyrillic"},
+ {0x01df, "adieresismacron"},
+ {0x1ea1, "adotbelow"},
+ {0x01e1, "adotmacron"},
{0x00e6, "ae"},
{0x01fd, "aeacute"},
+ {0x3150, "aekorean"},
+ {0x01e3, "aemacron"},
{0x2015, "afii00208"},
+ {0x20a4, "afii08941"},
{0x0410, "afii10017"},
{0x0411, "afii10018"},
{0x0412, "afii10019"},
@@ -596,499 +1078,3176 @@ static struct {
{0x066d, "afii63167"},
{0x02bd, "afii64937"},
{0x00e0, "agrave"},
+ {0x0a85, "agujarati"},
+ {0x0a05, "agurmukhi"},
+ {0x3042, "ahiragana"},
+ {0x1ea3, "ahookabove"},
+ {0x0990, "aibengali"},
+ {0x311e, "aibopomofo"},
+ {0x0910, "aideva"},
+ {0x04d5, "aiecyrillic"},
+ {0x0a90, "aigujarati"},
+ {0x0a10, "aigurmukhi"},
+ {0x0a48, "aimatragurmukhi"},
+ {0x0639, "ainarabic"},
+ {0xfeca, "ainfinalarabic"},
+ {0xfecb, "aininitialarabic"},
+ {0xfecc, "ainmedialarabic"},
+ {0x0203, "ainvertedbreve"},
+ {0x09c8, "aivowelsignbengali"},
+ {0x0948, "aivowelsigndeva"},
+ {0x0ac8, "aivowelsigngujarati"},
+ {0x30a2, "akatakana"},
+ {0xff71, "akatakanahalfwidth"},
+ {0x314f, "akorean"},
+ {0x05d0, "alef"},
+ {0x0627, "alefarabic"},
+ {0xfb30, "alefdageshhebrew"},
+ {0xfe8e, "aleffinalarabic"},
+ {0x0623, "alefhamzaabovearabic"},
+ {0xfe84, "alefhamzaabovefinalarabic"},
+ {0x0625, "alefhamzabelowarabic"},
+ {0xfe88, "alefhamzabelowfinalarabic"},
+ {0x05d0, "alefhebrew"},
+ {0xfb4f, "aleflamedhebrew"},
+ {0x0622, "alefmaddaabovearabic"},
+ {0xfe82, "alefmaddaabovefinalarabic"},
+ {0x0649, "alefmaksuraarabic"},
+ {0xfef0, "alefmaksurafinalarabic"},
+ {0xfef3, "alefmaksurainitialarabic"},
+ {0xfef4, "alefmaksuramedialarabic"},
+ {0xfb2e, "alefpatahhebrew"},
+ {0xfb2f, "alefqamatshebrew"},
{0x2135, "aleph"},
+ {0x224c, "allequal"},
{0x03b1, "alpha"},
{0x03ac, "alphatonos"},
{0x0101, "amacron"},
+ {0xff41, "amonospace"},
{0x0026, "ampersand"},
+ {0xff06, "ampersandmonospace"},
{0xf726, "ampersandsmall"},
+ {0x33c2, "amsquare"},
+ {0x3122, "anbopomofo"},
+ {0x3124, "angbopomofo"},
+ {0x0e5a, "angkhankhuthai"},
{0x2220, "angle"},
+ {0x3008, "anglebracketleft"},
+ {0xfe3f, "anglebracketleftvertical"},
+ {0x3009, "anglebracketright"},
+ {0xfe40, "anglebracketrightvertical"},
{0x2329, "angleleft"},
{0x232a, "angleright"},
+ {0x212b, "angstrom"},
{0x0387, "anoteleia"},
+ {0x0952, "anudattadeva"},
+ {0x0982, "anusvarabengali"},
+ {0x0902, "anusvaradeva"},
+ {0x0a82, "anusvaragujarati"},
{0x0105, "aogonek"},
+ {0x3300, "apaatosquare"},
+ {0x249c, "aparen"},
+ {0x055a, "apostrophearmenian"},
+ {0x02bc, "apostrophemod"},
+ {0xf8ff, "apple"},
+ {0x2250, "approaches"},
{0x2248, "approxequal"},
+ {0x2252, "approxequalorimage"},
+ {0x2245, "approximatelyequal"},
+ {0x318e, "araeaekorean"},
+ {0x318d, "araeakorean"},
+ {0x2312, "arc"},
+ {0x1e9a, "arighthalfring"},
{0x00e5, "aring"},
{0x01fb, "aringacute"},
+ {0x1e01, "aringbelow"},
{0x2194, "arrowboth"},
+ {0x21e3, "arrowdashdown"},
+ {0x21e0, "arrowdashleft"},
+ {0x21e2, "arrowdashright"},
+ {0x21e1, "arrowdashup"},
{0x21d4, "arrowdblboth"},
{0x21d3, "arrowdbldown"},
{0x21d0, "arrowdblleft"},
{0x21d2, "arrowdblright"},
{0x21d1, "arrowdblup"},
{0x2193, "arrowdown"},
+ {0x2199, "arrowdownleft"},
+ {0x2198, "arrowdownright"},
+ {0x21e9, "arrowdownwhite"},
+ {0x02c5, "arrowheaddownmod"},
+ {0x02c2, "arrowheadleftmod"},
+ {0x02c3, "arrowheadrightmod"},
+ {0x02c4, "arrowheadupmod"},
{0xf8e7, "arrowhorizex"},
{0x2190, "arrowleft"},
+ {0x21d0, "arrowleftdbl"},
+ {0x21cd, "arrowleftdblstroke"},
+ {0x21c6, "arrowleftoverright"},
+ {0x21e6, "arrowleftwhite"},
{0x2192, "arrowright"},
+ {0x21cf, "arrowrightdblstroke"},
+ {0x279e, "arrowrightheavy"},
+ {0x21c4, "arrowrightoverleft"},
+ {0x21e8, "arrowrightwhite"},
+ {0x21e4, "arrowtableft"},
+ {0x21e5, "arrowtabright"},
{0x2191, "arrowup"},
{0x2195, "arrowupdn"},
{0x21a8, "arrowupdnbse"},
+ {0x21a8, "arrowupdownbase"},
+ {0x2196, "arrowupleft"},
+ {0x21c5, "arrowupleftofdown"},
+ {0x2197, "arrowupright"},
+ {0x21e7, "arrowupwhite"},
{0xf8e6, "arrowvertex"},
{0x005e, "asciicircum"},
+ {0xff3e, "asciicircummonospace"},
{0x007e, "asciitilde"},
+ {0xff5e, "asciitildemonospace"},
+ {0x0251, "ascript"},
+ {0x0252, "ascriptturned"},
+ {0x3041, "asmallhiragana"},
+ {0x30a1, "asmallkatakana"},
+ {0xff67, "asmallkatakanahalfwidth"},
{0x002a, "asterisk"},
+ {0x066d, "asteriskaltonearabic"},
+ {0x066d, "asteriskarabic"},
{0x2217, "asteriskmath"},
+ {0xff0a, "asteriskmonospace"},
+ {0xfe61, "asterisksmall"},
+ {0x2042, "asterism"},
{0xf6e9, "asuperior"},
+ {0x2243, "asymptoticallyequal"},
{0x0040, "at"},
{0x00e3, "atilde"},
+ {0xff20, "atmonospace"},
+ {0xfe6b, "atsmall"},
+ {0x0250, "aturned"},
+ {0x0994, "aubengali"},
+ {0x3120, "aubopomofo"},
+ {0x0914, "audeva"},
+ {0x0a94, "augujarati"},
+ {0x0a14, "augurmukhi"},
+ {0x09d7, "aulengthmarkbengali"},
+ {0x0a4c, "aumatragurmukhi"},
+ {0x09cc, "auvowelsignbengali"},
+ {0x094c, "auvowelsigndeva"},
+ {0x0acc, "auvowelsigngujarati"},
+ {0x093d, "avagrahadeva"},
+ {0x0561, "aybarmenian"},
+ {0x05e2, "ayin"},
+ {0xfb20, "ayinaltonehebrew"},
+ {0x05e2, "ayinhebrew"},
{0x0062, "b"},
+ {0x09ac, "babengali"},
{0x005c, "backslash"},
+ {0xff3c, "backslashmonospace"},
+ {0x092c, "badeva"},
+ {0x0aac, "bagujarati"},
+ {0x0a2c, "bagurmukhi"},
+ {0x3070, "bahiragana"},
+ {0x0e3f, "bahtthai"},
+ {0x30d0, "bakatakana"},
{0x007c, "bar"},
+ {0xff5c, "barmonospace"},
+ {0x3105, "bbopomofo"},
+ {0x24d1, "bcircle"},
+ {0x1e03, "bdotaccent"},
+ {0x1e05, "bdotbelow"},
+ {0x266c, "beamedsixteenthnotes"},
+ {0x2235, "because"},
+ {0x0431, "becyrillic"},
+ {0x0628, "beharabic"},
+ {0xfe90, "behfinalarabic"},
+ {0xfe91, "behinitialarabic"},
+ {0x3079, "behiragana"},
+ {0xfe92, "behmedialarabic"},
+ {0xfc9f, "behmeeminitialarabic"},
+ {0xfc08, "behmeemisolatedarabic"},
+ {0xfc6d, "behnoonfinalarabic"},
+ {0x30d9, "bekatakana"},
+ {0x0562, "benarmenian"},
+ {0x05d1, "bet"},
{0x03b2, "beta"},
+ {0x03d0, "betasymbolgreek"},
+ {0xfb31, "betdagesh"},
+ {0xfb31, "betdageshhebrew"},
+ {0x05d1, "bethebrew"},
+ {0xfb4c, "betrafehebrew"},
+ {0x09ad, "bhabengali"},
+ {0x092d, "bhadeva"},
+ {0x0aad, "bhagujarati"},
+ {0x0a2d, "bhagurmukhi"},
+ {0x0253, "bhook"},
+ {0x3073, "bihiragana"},
+ {0x30d3, "bikatakana"},
+ {0x0298, "bilabialclick"},
+ {0x0a02, "bindigurmukhi"},
+ {0x3331, "birusquare"},
+ {0x25cf, "blackcircle"},
+ {0x25c6, "blackdiamond"},
+ {0x25bc, "blackdownpointingtriangle"},
+ {0x25c4, "blackleftpointingpointer"},
+ {0x25c0, "blackleftpointingtriangle"},
+ {0x3010, "blacklenticularbracketleft"},
+ {0xfe3b, "blacklenticularbracketleftvertical"},
+ {0x3011, "blacklenticularbracketright"},
+ {0xfe3c, "blacklenticularbracketrightvertical"},
+ {0x25e3, "blacklowerlefttriangle"},
+ {0x25e2, "blacklowerrighttriangle"},
+ {0x25ac, "blackrectangle"},
+ {0x25ba, "blackrightpointingpointer"},
+ {0x25b6, "blackrightpointingtriangle"},
+ {0x25aa, "blacksmallsquare"},
+ {0x263b, "blacksmilingface"},
+ {0x25a0, "blacksquare"},
+ {0x2605, "blackstar"},
+ {0x25e4, "blackupperlefttriangle"},
+ {0x25e5, "blackupperrighttriangle"},
+ {0x25b4, "blackuppointingsmalltriangle"},
+ {0x25b2, "blackuppointingtriangle"},
+ {0x2423, "blank"},
+ {0x1e07, "blinebelow"},
{0x2588, "block"},
+ {0xff42, "bmonospace"},
+ {0x0e1a, "bobaimaithai"},
+ {0x307c, "bohiragana"},
+ {0x30dc, "bokatakana"},
+ {0x249d, "bparen"},
+ {0x33c3, "bqsquare"},
{0xf8f4, "braceex"},
{0x007b, "braceleft"},
{0xf8f3, "braceleftbt"},
{0xf8f2, "braceleftmid"},
+ {0xff5b, "braceleftmonospace"},
+ {0xfe5b, "braceleftsmall"},
{0xf8f1, "bracelefttp"},
+ {0xfe37, "braceleftvertical"},
{0x007d, "braceright"},
{0xf8fe, "bracerightbt"},
{0xf8fd, "bracerightmid"},
+ {0xff5d, "bracerightmonospace"},
+ {0xfe5c, "bracerightsmall"},
{0xf8fc, "bracerighttp"},
+ {0xfe38, "bracerightvertical"},
{0x005b, "bracketleft"},
{0xf8f0, "bracketleftbt"},
{0xf8ef, "bracketleftex"},
+ {0xff3b, "bracketleftmonospace"},
{0xf8ee, "bracketlefttp"},
{0x005d, "bracketright"},
{0xf8fb, "bracketrightbt"},
{0xf8fa, "bracketrightex"},
+ {0xff3d, "bracketrightmonospace"},
{0xf8f9, "bracketrighttp"},
{0x02d8, "breve"},
+ {0x032e, "brevebelowcmb"},
+ {0x0306, "brevecmb"},
+ {0x032f, "breveinvertedbelowcmb"},
+ {0x0311, "breveinvertedcmb"},
+ {0x0361, "breveinverteddoublecmb"},
+ {0x032a, "bridgebelowcmb"},
+ {0x033a, "bridgeinvertedbelowcmb"},
{0x00a6, "brokenbar"},
+ {0x0180, "bstroke"},
{0xf6ea, "bsuperior"},
+ {0x0183, "btopbar"},
+ {0x3076, "buhiragana"},
+ {0x30d6, "bukatakana"},
{0x2022, "bullet"},
+ {0x25d8, "bulletinverse"},
+ {0x2219, "bulletoperator"},
+ {0x25ce, "bullseye"},
{0x0063, "c"},
+ {0x056e, "caarmenian"},
+ {0x099a, "cabengali"},
{0x0107, "cacute"},
+ {0x091a, "cadeva"},
+ {0x0a9a, "cagujarati"},
+ {0x0a1a, "cagurmukhi"},
+ {0x3388, "calsquare"},
+ {0x0981, "candrabindubengali"},
+ {0x0310, "candrabinducmb"},
+ {0x0901, "candrabindudeva"},
+ {0x0a81, "candrabindugujarati"},
+ {0x21ea, "capslock"},
+ {0x2105, "careof"},
{0x02c7, "caron"},
+ {0x032c, "caronbelowcmb"},
+ {0x030c, "caroncmb"},
{0x21b5, "carriagereturn"},
+ {0x3118, "cbopomofo"},
{0x010d, "ccaron"},
{0x00e7, "ccedilla"},
+ {0x1e09, "ccedillaacute"},
+ {0x24d2, "ccircle"},
{0x0109, "ccircumflex"},
+ {0x0255, "ccurl"},
+ {0x010b, "cdot"},
{0x010b, "cdotaccent"},
+ {0x33c5, "cdsquare"},
{0x00b8, "cedilla"},
+ {0x0327, "cedillacmb"},
{0x00a2, "cent"},
+ {0x2103, "centigrade"},
{0xf6df, "centinferior"},
+ {0xffe0, "centmonospace"},
{0xf7a2, "centoldstyle"},
{0xf6e0, "centsuperior"},
+ {0x0579, "chaarmenian"},
+ {0x099b, "chabengali"},
+ {0x091b, "chadeva"},
+ {0x0a9b, "chagujarati"},
+ {0x0a1b, "chagurmukhi"},
+ {0x3114, "chbopomofo"},
+ {0x04bd, "cheabkhasiancyrillic"},
+ {0x2713, "checkmark"},
+ {0x0447, "checyrillic"},
+ {0x04bf, "chedescenderabkhasiancyrillic"},
+ {0x04b7, "chedescendercyrillic"},
+ {0x04f5, "chedieresiscyrillic"},
+ {0x0573, "cheharmenian"},
+ {0x04cc, "chekhakassiancyrillic"},
+ {0x04b9, "cheverticalstrokecyrillic"},
{0x03c7, "chi"},
+ {0x3277, "chieuchacirclekorean"},
+ {0x3217, "chieuchaparenkorean"},
+ {0x3269, "chieuchcirclekorean"},
+ {0x314a, "chieuchkorean"},
+ {0x3209, "chieuchparenkorean"},
+ {0x0e0a, "chochangthai"},
+ {0x0e08, "chochanthai"},
+ {0x0e09, "chochingthai"},
+ {0x0e0c, "chochoethai"},
+ {0x0188, "chook"},
+ {0x3276, "cieucacirclekorean"},
+ {0x3216, "cieucaparenkorean"},
+ {0x3268, "cieuccirclekorean"},
+ {0x3148, "cieuckorean"},
+ {0x3208, "cieucparenkorean"},
+ {0x321c, "cieucuparenkorean"},
{0x25cb, "circle"},
{0x2297, "circlemultiply"},
+ {0x2299, "circleot"},
{0x2295, "circleplus"},
+ {0x3036, "circlepostalmark"},
+ {0x25d0, "circlewithlefthalfblack"},
+ {0x25d1, "circlewithrighthalfblack"},
{0x02c6, "circumflex"},
+ {0x032d, "circumflexbelowcmb"},
+ {0x0302, "circumflexcmb"},
+ {0x2327, "clear"},
+ {0x01c2, "clickalveolar"},
+ {0x01c0, "clickdental"},
+ {0x01c1, "clicklateral"},
+ {0x01c3, "clickretroflex"},
{0x2663, "club"},
+ {0x2663, "clubsuitblack"},
+ {0x2667, "clubsuitwhite"},
+ {0x33a4, "cmcubedsquare"},
+ {0xff43, "cmonospace"},
+ {0x33a0, "cmsquaredsquare"},
+ {0x0581, "coarmenian"},
{0x003a, "colon"},
{0x20a1, "colonmonetary"},
+ {0xff1a, "colonmonospace"},
+ {0x20a1, "colonsign"},
+ {0xfe55, "colonsmall"},
+ {0x02d1, "colontriangularhalfmod"},
+ {0x02d0, "colontriangularmod"},
{0x002c, "comma"},
+ {0x0313, "commaabovecmb"},
+ {0x0315, "commaaboverightcmb"},
{0xf6c3, "commaaccent"},
+ {0x060c, "commaarabic"},
+ {0x055d, "commaarmenian"},
{0xf6e1, "commainferior"},
+ {0xff0c, "commamonospace"},
+ {0x0314, "commareversedabovecmb"},
+ {0x02bd, "commareversedmod"},
+ {0xfe50, "commasmall"},
{0xf6e2, "commasuperior"},
+ {0x0312, "commaturnedabovecmb"},
+ {0x02bb, "commaturnedmod"},
+ {0x263c, "compass"},
{0x2245, "congruent"},
+ {0x222e, "contourintegral"},
+ {0x2303, "control"},
+ {0x0006, "controlACK"},
+ {0x0007, "controlBEL"},
+ {0x0008, "controlBS"},
+ {0x0018, "controlCAN"},
+ {0x000d, "controlCR"},
+ {0x0011, "controlDC1"},
+ {0x0012, "controlDC2"},
+ {0x0013, "controlDC3"},
+ {0x0014, "controlDC4"},
+ {0x007f, "controlDEL"},
+ {0x0010, "controlDLE"},
+ {0x0019, "controlEM"},
+ {0x0005, "controlENQ"},
+ {0x0004, "controlEOT"},
+ {0x001b, "controlESC"},
+ {0x0017, "controlETB"},
+ {0x0003, "controlETX"},
+ {0x000c, "controlFF"},
+ {0x001c, "controlFS"},
+ {0x001d, "controlGS"},
+ {0x0009, "controlHT"},
+ {0x000a, "controlLF"},
+ {0x0015, "controlNAK"},
+ {0x001e, "controlRS"},
+ {0x000f, "controlSI"},
+ {0x000e, "controlSO"},
+ {0x0002, "controlSOT"},
+ {0x0001, "controlSTX"},
+ {0x001a, "controlSUB"},
+ {0x0016, "controlSYN"},
+ {0x001f, "controlUS"},
+ {0x000b, "controlVT"},
{0x00a9, "copyright"},
{0x00a9, "copyrightsans"},
{0x00a9, "copyrightserif"},
+ {0x300c, "cornerbracketleft"},
+ {0xff62, "cornerbracketlefthalfwidth"},
+ {0xfe41, "cornerbracketleftvertical"},
+ {0x300d, "cornerbracketright"},
+ {0xff63, "cornerbracketrighthalfwidth"},
+ {0xfe42, "cornerbracketrightvertical"},
+ {0x337f, "corporationsquare"},
+ {0x33c7, "cosquare"},
+ {0x33c6, "coverkgsquare"},
+ {0x249e, "cparen"},
+ {0x20a2, "cruzeiro"},
+ {0x0297, "cstretched"},
+ {0x22cf, "curlyand"},
+ {0x22ce, "curlyor"},
{0x00a4, "currency"},
{0xf6d1, "cyrBreve"},
{0xf6d2, "cyrFlex"},
{0xf6d4, "cyrbreve"},
{0xf6d5, "cyrflex"},
{0x0064, "d"},
+ {0x0564, "daarmenian"},
+ {0x09a6, "dabengali"},
+ {0x0636, "dadarabic"},
+ {0x0926, "dadeva"},
+ {0xfebe, "dadfinalarabic"},
+ {0xfebf, "dadinitialarabic"},
+ {0xfec0, "dadmedialarabic"},
+ {0x05bc, "dagesh"},
+ {0x05bc, "dageshhebrew"},
{0x2020, "dagger"},
{0x2021, "daggerdbl"},
+ {0x0aa6, "dagujarati"},
+ {0x0a26, "dagurmukhi"},
+ {0x3060, "dahiragana"},
+ {0x30c0, "dakatakana"},
+ {0x062f, "dalarabic"},
+ {0x05d3, "dalet"},
+ {0xfb33, "daletdagesh"},
+ {0xfb33, "daletdageshhebrew"},
+ {0x05d3, "dalethebrew"},
+ {0xfeaa, "dalfinalarabic"},
+ {0x064f, "dammaarabic"},
+ {0x064f, "dammalowarabic"},
+ {0x064c, "dammatanaltonearabic"},
+ {0x064c, "dammatanarabic"},
+ {0x0964, "danda"},
+ {0x05a7, "dargahebrew"},
+ {0x05a7, "dargalefthebrew"},
+ {0x0485, "dasiapneumatacyrilliccmb"},
{0xf6d3, "dblGrave"},
+ {0x300a, "dblanglebracketleft"},
+ {0xfe3d, "dblanglebracketleftvertical"},
+ {0x300b, "dblanglebracketright"},
+ {0xfe3e, "dblanglebracketrightvertical"},
+ {0x032b, "dblarchinvertedbelowcmb"},
+ {0x21d4, "dblarrowleft"},
+ {0x21d2, "dblarrowright"},
+ {0x0965, "dbldanda"},
{0xf6d6, "dblgrave"},
+ {0x030f, "dblgravecmb"},
+ {0x222c, "dblintegral"},
+ {0x2017, "dbllowline"},
+ {0x0333, "dbllowlinecmb"},
+ {0x033f, "dbloverlinecmb"},
+ {0x02ba, "dblprimemod"},
+ {0x2016, "dblverticalbar"},
+ {0x030e, "dblverticallineabovecmb"},
+ {0x3109, "dbopomofo"},
+ {0x33c8, "dbsquare"},
{0x010f, "dcaron"},
+ {0x1e11, "dcedilla"},
+ {0x24d3, "dcircle"},
+ {0x1e13, "dcircumflexbelow"},
{0x0111, "dcroat"},
+ {0x09a1, "ddabengali"},
+ {0x0921, "ddadeva"},
+ {0x0aa1, "ddagujarati"},
+ {0x0a21, "ddagurmukhi"},
+ {0x0688, "ddalarabic"},
+ {0xfb89, "ddalfinalarabic"},
+ {0x095c, "dddhadeva"},
+ {0x09a2, "ddhabengali"},
+ {0x0922, "ddhadeva"},
+ {0x0aa2, "ddhagujarati"},
+ {0x0a22, "ddhagurmukhi"},
+ {0x1e0b, "ddotaccent"},
+ {0x1e0d, "ddotbelow"},
+ {0x066b, "decimalseparatorarabic"},
+ {0x066b, "decimalseparatorpersian"},
+ {0x0434, "decyrillic"},
{0x00b0, "degree"},
+ {0x05ad, "dehihebrew"},
+ {0x3067, "dehiragana"},
+ {0x03ef, "deicoptic"},
+ {0x30c7, "dekatakana"},
+ {0x232b, "deleteleft"},
+ {0x2326, "deleteright"},
{0x03b4, "delta"},
+ {0x018d, "deltaturned"},
+ {0x09f8, "denominatorminusonenumeratorbengali"},
+ {0x02a4, "dezh"},
+ {0x09a7, "dhabengali"},
+ {0x0927, "dhadeva"},
+ {0x0aa7, "dhagujarati"},
+ {0x0a27, "dhagurmukhi"},
+ {0x0257, "dhook"},
+ {0x0385, "dialytikatonos"},
+ {0x0344, "dialytikatonoscmb"},
{0x2666, "diamond"},
+ {0x2662, "diamondsuitwhite"},
{0x00a8, "dieresis"},
{0xf6d7, "dieresisacute"},
+ {0x0324, "dieresisbelowcmb"},
+ {0x0308, "dieresiscmb"},
{0xf6d8, "dieresisgrave"},
{0x0385, "dieresistonos"},
+ {0x3062, "dihiragana"},
+ {0x30c2, "dikatakana"},
+ {0x3003, "dittomark"},
{0x00f7, "divide"},
+ {0x2223, "divides"},
+ {0x2215, "divisionslash"},
+ {0x0452, "djecyrillic"},
{0x2593, "dkshade"},
+ {0x1e0f, "dlinebelow"},
+ {0x3397, "dlsquare"},
+ {0x0111, "dmacron"},
+ {0xff44, "dmonospace"},
{0x2584, "dnblock"},
+ {0x0e0e, "dochadathai"},
+ {0x0e14, "dodekthai"},
+ {0x3069, "dohiragana"},
+ {0x30c9, "dokatakana"},
{0x0024, "dollar"},
{0xf6e3, "dollarinferior"},
+ {0xff04, "dollarmonospace"},
{0xf724, "dollaroldstyle"},
+ {0xfe69, "dollarsmall"},
{0xf6e4, "dollarsuperior"},
{0x20ab, "dong"},
+ {0x3326, "dorusquare"},
{0x02d9, "dotaccent"},
+ {0x0307, "dotaccentcmb"},
+ {0x0323, "dotbelowcmb"},
{0x0323, "dotbelowcomb"},
+ {0x30fb, "dotkatakana"},
{0x0131, "dotlessi"},
{0xf6be, "dotlessj"},
+ {0x0284, "dotlessjstrokehook"},
{0x22c5, "dotmath"},
+ {0x25cc, "dottedcircle"},
+ {0xfb1f, "doubleyodpatah"},
+ {0xfb1f, "doubleyodpatahhebrew"},
+ {0x031e, "downtackbelowcmb"},
+ {0x02d5, "downtackmod"},
+ {0x249f, "dparen"},
{0xf6eb, "dsuperior"},
+ {0x0256, "dtail"},
+ {0x018c, "dtopbar"},
+ {0x3065, "duhiragana"},
+ {0x30c5, "dukatakana"},
+ {0x01f3, "dz"},
+ {0x02a3, "dzaltone"},
+ {0x01c6, "dzcaron"},
+ {0x02a5, "dzcurl"},
+ {0x04e1, "dzeabkhasiancyrillic"},
+ {0x0455, "dzecyrillic"},
+ {0x045f, "dzhecyrillic"},
{0x0065, "e"},
{0x00e9, "eacute"},
+ {0x2641, "earth"},
+ {0x098f, "ebengali"},
+ {0x311c, "ebopomofo"},
{0x0115, "ebreve"},
+ {0x090d, "ecandradeva"},
+ {0x0a8d, "ecandragujarati"},
+ {0x0945, "ecandravowelsigndeva"},
+ {0x0ac5, "ecandravowelsigngujarati"},
{0x011b, "ecaron"},
+ {0x1e1d, "ecedillabreve"},
+ {0x0565, "echarmenian"},
+ {0x0587, "echyiwnarmenian"},
+ {0x24d4, "ecircle"},
{0x00ea, "ecircumflex"},
+ {0x1ebf, "ecircumflexacute"},
+ {0x1e19, "ecircumflexbelow"},
+ {0x1ec7, "ecircumflexdotbelow"},
+ {0x1ec1, "ecircumflexgrave"},
+ {0x1ec3, "ecircumflexhookabove"},
+ {0x1ec5, "ecircumflextilde"},
+ {0x0454, "ecyrillic"},
+ {0x0205, "edblgrave"},
+ {0x090f, "edeva"},
{0x00eb, "edieresis"},
+ {0x0117, "edot"},
{0x0117, "edotaccent"},
+ {0x1eb9, "edotbelow"},
+ {0x0a0f, "eegurmukhi"},
+ {0x0a47, "eematragurmukhi"},
+ {0x0444, "efcyrillic"},
{0x00e8, "egrave"},
+ {0x0a8f, "egujarati"},
+ {0x0567, "eharmenian"},
+ {0x311d, "ehbopomofo"},
+ {0x3048, "ehiragana"},
+ {0x1ebb, "ehookabove"},
+ {0x311f, "eibopomofo"},
{0x0038, "eight"},
+ {0x0668, "eightarabic"},
+ {0x09ee, "eightbengali"},
+ {0x2467, "eightcircle"},
+ {0x2791, "eightcircleinversesansserif"},
+ {0x096e, "eightdeva"},
+ {0x2471, "eighteencircle"},
+ {0x2485, "eighteenparen"},
+ {0x2499, "eighteenperiod"},
+ {0x0aee, "eightgujarati"},
+ {0x0a6e, "eightgurmukhi"},
+ {0x0668, "eighthackarabic"},
+ {0x3028, "eighthangzhou"},
+ {0x266b, "eighthnotebeamed"},
+ {0x3227, "eightideographicparen"},
{0x2088, "eightinferior"},
+ {0xff18, "eightmonospace"},
{0xf738, "eightoldstyle"},
+ {0x247b, "eightparen"},
+ {0x248f, "eightperiod"},
+ {0x06f8, "eightpersian"},
+ {0x2177, "eightroman"},
{0x2078, "eightsuperior"},
+ {0x0e58, "eightthai"},
+ {0x0207, "einvertedbreve"},
+ {0x0465, "eiotifiedcyrillic"},
+ {0x30a8, "ekatakana"},
+ {0xff74, "ekatakanahalfwidth"},
+ {0x0a74, "ekonkargurmukhi"},
+ {0x3154, "ekorean"},
+ {0x043b, "elcyrillic"},
{0x2208, "element"},
+ {0x246a, "elevencircle"},
+ {0x247e, "elevenparen"},
+ {0x2492, "elevenperiod"},
+ {0x217a, "elevenroman"},
{0x2026, "ellipsis"},
+ {0x22ee, "ellipsisvertical"},
{0x0113, "emacron"},
+ {0x1e17, "emacronacute"},
+ {0x1e15, "emacrongrave"},
+ {0x043c, "emcyrillic"},
{0x2014, "emdash"},
+ {0xfe31, "emdashvertical"},
+ {0xff45, "emonospace"},
+ {0x055b, "emphasismarkarmenian"},
{0x2205, "emptyset"},
+ {0x3123, "enbopomofo"},
+ {0x043d, "encyrillic"},
{0x2013, "endash"},
+ {0xfe32, "endashvertical"},
+ {0x04a3, "endescendercyrillic"},
{0x014b, "eng"},
+ {0x3125, "engbopomofo"},
+ {0x04a5, "enghecyrillic"},
+ {0x04c8, "enhookcyrillic"},
+ {0x2002, "enspace"},
{0x0119, "eogonek"},
+ {0x3153, "eokorean"},
+ {0x025b, "eopen"},
+ {0x029a, "eopenclosed"},
+ {0x025c, "eopenreversed"},
+ {0x025e, "eopenreversedclosed"},
+ {0x025d, "eopenreversedhook"},
+ {0x24a0, "eparen"},
{0x03b5, "epsilon"},
{0x03ad, "epsilontonos"},
{0x003d, "equal"},
+ {0xff1d, "equalmonospace"},
+ {0xfe66, "equalsmall"},
+ {0x207c, "equalsuperior"},
{0x2261, "equivalence"},
+ {0x3126, "erbopomofo"},
+ {0x0440, "ercyrillic"},
+ {0x0258, "ereversed"},
+ {0x044d, "ereversedcyrillic"},
+ {0x0441, "escyrillic"},
+ {0x04ab, "esdescendercyrillic"},
+ {0x0283, "esh"},
+ {0x0286, "eshcurl"},
+ {0x090e, "eshortdeva"},
+ {0x0946, "eshortvowelsigndeva"},
+ {0x01aa, "eshreversedloop"},
+ {0x0285, "eshsquatreversed"},
+ {0x3047, "esmallhiragana"},
+ {0x30a7, "esmallkatakana"},
+ {0xff6a, "esmallkatakanahalfwidth"},
{0x212e, "estimated"},
{0xf6ec, "esuperior"},
{0x03b7, "eta"},
+ {0x0568, "etarmenian"},
{0x03ae, "etatonos"},
{0x00f0, "eth"},
+ {0x1ebd, "etilde"},
+ {0x1e1b, "etildebelow"},
+ {0x0591, "etnahtafoukhhebrew"},
+ {0x0591, "etnahtafoukhlefthebrew"},
+ {0x0591, "etnahtahebrew"},
+ {0x0591, "etnahtalefthebrew"},
+ {0x01dd, "eturned"},
+ {0x3161, "eukorean"},
+ {0x20ac, "euro"},
+ {0x09c7, "evowelsignbengali"},
+ {0x0947, "evowelsigndeva"},
+ {0x0ac7, "evowelsigngujarati"},
{0x0021, "exclam"},
+ {0x055c, "exclamarmenian"},
{0x203c, "exclamdbl"},
{0x00a1, "exclamdown"},
{0xf7a1, "exclamdownsmall"},
{0x0021, "exclamleft"},
+ {0xff01, "exclammonospace"},
{0xf721, "exclamsmall"},
{0x2203, "existential"},
+ {0x0292, "ezh"},
+ {0x01ef, "ezhcaron"},
+ {0x0293, "ezhcurl"},
+ {0x01b9, "ezhreversed"},
+ {0x01ba, "ezhtail"},
{0x0066, "f"},
+ {0x095e, "fadeva"},
+ {0x0a5e, "fagurmukhi"},
+ {0x2109, "fahrenheit"},
+ {0x064e, "fathaarabic"},
+ {0x064e, "fathalowarabic"},
+ {0x064b, "fathatanarabic"},
+ {0x3108, "fbopomofo"},
+ {0x24d5, "fcircle"},
+ {0x1e1f, "fdotaccent"},
+ {0x0641, "feharabic"},
+ {0x0586, "feharmenian"},
+ {0xfed2, "fehfinalarabic"},
+ {0xfed3, "fehinitialarabic"},
+ {0xfed4, "fehmedialarabic"},
+ {0x03e5, "feicoptic"},
{0x2640, "female"},
{0xfb00, "ff"},
{0xfb03, "ffi"},
{0xfb04, "ffl"},
{0xfb01, "fi"},
+ {0x246e, "fifteencircle"},
+ {0x2482, "fifteenparen"},
+ {0x2496, "fifteenperiod"},
{0x2012, "figuredash"},
{0x25a0, "filledbox"},
{0x25ac, "filledrect"},
+ {0x05da, "finalkaf"},
+ {0xfb3a, "finalkafdagesh"},
+ {0xfb3a, "finalkafdageshhebrew"},
+ {0x05da, "finalkafhebrew"},
+ {0x05dd, "finalmem"},
+ {0x05dd, "finalmemhebrew"},
+ {0x05df, "finalnun"},
+ {0x05df, "finalnunhebrew"},
+ {0x05e3, "finalpe"},
+ {0x05e3, "finalpehebrew"},
+ {0x05e5, "finaltsadi"},
+ {0x05e5, "finaltsadihebrew"},
+ {0x02c9, "firsttonechinese"},
+ {0x25c9, "fisheye"},
+ {0x0473, "fitacyrillic"},
{0x0035, "five"},
+ {0x0665, "fivearabic"},
+ {0x09eb, "fivebengali"},
+ {0x2464, "fivecircle"},
+ {0x278e, "fivecircleinversesansserif"},
+ {0x096b, "fivedeva"},
{0x215d, "fiveeighths"},
+ {0x0aeb, "fivegujarati"},
+ {0x0a6b, "fivegurmukhi"},
+ {0x0665, "fivehackarabic"},
+ {0x3025, "fivehangzhou"},
+ {0x3224, "fiveideographicparen"},
{0x2085, "fiveinferior"},
+ {0xff15, "fivemonospace"},
{0xf735, "fiveoldstyle"},
+ {0x2478, "fiveparen"},
+ {0x248c, "fiveperiod"},
+ {0x06f5, "fivepersian"},
+ {0x2174, "fiveroman"},
{0x2075, "fivesuperior"},
+ {0x0e55, "fivethai"},
{0xfb02, "fl"},
{0x0192, "florin"},
+ {0xff46, "fmonospace"},
+ {0x3399, "fmsquare"},
+ {0x0e1f, "fofanthai"},
+ {0x0e1d, "fofathai"},
+ {0x0e4f, "fongmanthai"},
+ {0x2200, "forall"},
{0x0034, "four"},
+ {0x0664, "fourarabic"},
+ {0x09ea, "fourbengali"},
+ {0x2463, "fourcircle"},
+ {0x278d, "fourcircleinversesansserif"},
+ {0x096a, "fourdeva"},
+ {0x0aea, "fourgujarati"},
+ {0x0a6a, "fourgurmukhi"},
+ {0x0664, "fourhackarabic"},
+ {0x3024, "fourhangzhou"},
+ {0x3223, "fourideographicparen"},
{0x2084, "fourinferior"},
+ {0xff14, "fourmonospace"},
+ {0x09f7, "fournumeratorbengali"},
{0xf734, "fouroldstyle"},
+ {0x2477, "fourparen"},
+ {0x248b, "fourperiod"},
+ {0x06f4, "fourpersian"},
+ {0x2173, "fourroman"},
{0x2074, "foursuperior"},
+ {0x246d, "fourteencircle"},
+ {0x2481, "fourteenparen"},
+ {0x2495, "fourteenperiod"},
+ {0x0e54, "fourthai"},
+ {0x02cb, "fourthtonechinese"},
+ {0x24a1, "fparen"},
{0x2044, "fraction"},
{0x20a3, "franc"},
{0x0067, "g"},
+ {0x0997, "gabengali"},
+ {0x01f5, "gacute"},
+ {0x0917, "gadeva"},
+ {0x06af, "gafarabic"},
+ {0xfb93, "gaffinalarabic"},
+ {0xfb94, "gafinitialarabic"},
+ {0xfb95, "gafmedialarabic"},
+ {0x0a97, "gagujarati"},
+ {0x0a17, "gagurmukhi"},
+ {0x304c, "gahiragana"},
+ {0x30ac, "gakatakana"},
{0x03b3, "gamma"},
+ {0x0263, "gammalatinsmall"},
+ {0x02e0, "gammasuperior"},
+ {0x03eb, "gangiacoptic"},
+ {0x310d, "gbopomofo"},
{0x011f, "gbreve"},
{0x01e7, "gcaron"},
+ {0x0123, "gcedilla"},
+ {0x24d6, "gcircle"},
{0x011d, "gcircumflex"},
{0x0123, "gcommaaccent"},
+ {0x0121, "gdot"},
{0x0121, "gdotaccent"},
+ {0x0433, "gecyrillic"},
+ {0x3052, "gehiragana"},
+ {0x30b2, "gekatakana"},
+ {0x2251, "geometricallyequal"},
+ {0x059c, "gereshaccenthebrew"},
+ {0x05f3, "gereshhebrew"},
+ {0x059d, "gereshmuqdamhebrew"},
{0x00df, "germandbls"},
+ {0x059e, "gershayimaccenthebrew"},
+ {0x05f4, "gershayimhebrew"},
+ {0x3013, "getamark"},
+ {0x0998, "ghabengali"},
+ {0x0572, "ghadarmenian"},
+ {0x0918, "ghadeva"},
+ {0x0a98, "ghagujarati"},
+ {0x0a18, "ghagurmukhi"},
+ {0x063a, "ghainarabic"},
+ {0xfece, "ghainfinalarabic"},
+ {0xfecf, "ghaininitialarabic"},
+ {0xfed0, "ghainmedialarabic"},
+ {0x0495, "ghemiddlehookcyrillic"},
+ {0x0493, "ghestrokecyrillic"},
+ {0x0491, "gheupturncyrillic"},
+ {0x095a, "ghhadeva"},
+ {0x0a5a, "ghhagurmukhi"},
+ {0x0260, "ghook"},
+ {0x3393, "ghzsquare"},
+ {0x304e, "gihiragana"},
+ {0x30ae, "gikatakana"},
+ {0x0563, "gimarmenian"},
+ {0x05d2, "gimel"},
+ {0xfb32, "gimeldagesh"},
+ {0xfb32, "gimeldageshhebrew"},
+ {0x05d2, "gimelhebrew"},
+ {0x0453, "gjecyrillic"},
+ {0x01be, "glottalinvertedstroke"},
+ {0x0294, "glottalstop"},
+ {0x0296, "glottalstopinverted"},
+ {0x02c0, "glottalstopmod"},
+ {0x0295, "glottalstopreversed"},
+ {0x02c1, "glottalstopreversedmod"},
+ {0x02e4, "glottalstopreversedsuperior"},
+ {0x02a1, "glottalstopstroke"},
+ {0x02a2, "glottalstopstrokereversed"},
+ {0x1e21, "gmacron"},
+ {0xff47, "gmonospace"},
+ {0x3054, "gohiragana"},
+ {0x30b4, "gokatakana"},
+ {0x24a2, "gparen"},
+ {0x33ac, "gpasquare"},
{0x2207, "gradient"},
{0x0060, "grave"},
+ {0x0316, "gravebelowcmb"},
+ {0x0300, "gravecmb"},
{0x0300, "gravecomb"},
+ {0x0953, "gravedeva"},
+ {0x02ce, "gravelowmod"},
+ {0xff40, "gravemonospace"},
+ {0x0340, "gravetonecmb"},
{0x003e, "greater"},
{0x2265, "greaterequal"},
+ {0x22db, "greaterequalorless"},
+ {0xff1e, "greatermonospace"},
+ {0x2273, "greaterorequivalent"},
+ {0x2277, "greaterorless"},
+ {0x2267, "greateroverequal"},
+ {0xfe65, "greatersmall"},
+ {0x0261, "gscript"},
+ {0x01e5, "gstroke"},
+ {0x3050, "guhiragana"},
{0x00ab, "guillemotleft"},
{0x00bb, "guillemotright"},
{0x2039, "guilsinglleft"},
{0x203a, "guilsinglright"},
+ {0x30b0, "gukatakana"},
+ {0x3318, "guramusquare"},
+ {0x33c9, "gysquare"},
{0x0068, "h"},
+ {0x04a9, "haabkhasiancyrillic"},
+ {0x06c1, "haaltonearabic"},
+ {0x09b9, "habengali"},
+ {0x04b3, "hadescendercyrillic"},
+ {0x0939, "hadeva"},
+ {0x0ab9, "hagujarati"},
+ {0x0a39, "hagurmukhi"},
+ {0x062d, "haharabic"},
+ {0xfea2, "hahfinalarabic"},
+ {0xfea3, "hahinitialarabic"},
+ {0x306f, "hahiragana"},
+ {0xfea4, "hahmedialarabic"},
+ {0x332a, "haitusquare"},
+ {0x30cf, "hakatakana"},
+ {0xff8a, "hakatakanahalfwidth"},
+ {0x0a4d, "halantgurmukhi"},
+ {0x0621, "hamzaarabic"},
+ {0x0621, "hamzalowarabic"},
+ {0x3164, "hangulfiller"},
+ {0x044a, "hardsigncyrillic"},
+ {0x21bc, "harpoonleftbarbup"},
+ {0x21c0, "harpoonrightbarbup"},
+ {0x33ca, "hasquare"},
+ {0x05b2, "hatafpatah"},
+ {0x05b2, "hatafpatah16"},
+ {0x05b2, "hatafpatah23"},
+ {0x05b2, "hatafpatah2f"},
+ {0x05b2, "hatafpatahhebrew"},
+ {0x05b2, "hatafpatahnarrowhebrew"},
+ {0x05b2, "hatafpatahquarterhebrew"},
+ {0x05b2, "hatafpatahwidehebrew"},
+ {0x05b3, "hatafqamats"},
+ {0x05b3, "hatafqamats1b"},
+ {0x05b3, "hatafqamats28"},
+ {0x05b3, "hatafqamats34"},
+ {0x05b3, "hatafqamatshebrew"},
+ {0x05b3, "hatafqamatsnarrowhebrew"},
+ {0x05b3, "hatafqamatsquarterhebrew"},
+ {0x05b3, "hatafqamatswidehebrew"},
+ {0x05b1, "hatafsegol"},
+ {0x05b1, "hatafsegol17"},
+ {0x05b1, "hatafsegol24"},
+ {0x05b1, "hatafsegol30"},
+ {0x05b1, "hatafsegolhebrew"},
+ {0x05b1, "hatafsegolnarrowhebrew"},
+ {0x05b1, "hatafsegolquarterhebrew"},
+ {0x05b1, "hatafsegolwidehebrew"},
{0x0127, "hbar"},
+ {0x310f, "hbopomofo"},
+ {0x1e2b, "hbrevebelow"},
+ {0x1e29, "hcedilla"},
+ {0x24d7, "hcircle"},
{0x0125, "hcircumflex"},
+ {0x1e27, "hdieresis"},
+ {0x1e23, "hdotaccent"},
+ {0x1e25, "hdotbelow"},
+ {0x05d4, "he"},
{0x2665, "heart"},
+ {0x2665, "heartsuitblack"},
+ {0x2661, "heartsuitwhite"},
+ {0xfb34, "hedagesh"},
+ {0xfb34, "hedageshhebrew"},
+ {0x06c1, "hehaltonearabic"},
+ {0x0647, "heharabic"},
+ {0x05d4, "hehebrew"},
+ {0xfba7, "hehfinalaltonearabic"},
+ {0xfeea, "hehfinalalttwoarabic"},
+ {0xfeea, "hehfinalarabic"},
+ {0xfba5, "hehhamzaabovefinalarabic"},
+ {0xfba4, "hehhamzaaboveisolatedarabic"},
+ {0xfba8, "hehinitialaltonearabic"},
+ {0xfeeb, "hehinitialarabic"},
+ {0x3078, "hehiragana"},
+ {0xfba9, "hehmedialaltonearabic"},
+ {0xfeec, "hehmedialarabic"},
+ {0x337b, "heiseierasquare"},
+ {0x30d8, "hekatakana"},
+ {0xff8d, "hekatakanahalfwidth"},
+ {0x3336, "hekutaarusquare"},
+ {0x0267, "henghook"},
+ {0x3339, "herutusquare"},
+ {0x05d7, "het"},
+ {0x05d7, "hethebrew"},
+ {0x0266, "hhook"},
+ {0x02b1, "hhooksuperior"},
+ {0x327b, "hieuhacirclekorean"},
+ {0x321b, "hieuhaparenkorean"},
+ {0x326d, "hieuhcirclekorean"},
+ {0x314e, "hieuhkorean"},
+ {0x320d, "hieuhparenkorean"},
+ {0x3072, "hihiragana"},
+ {0x30d2, "hikatakana"},
+ {0xff8b, "hikatakanahalfwidth"},
+ {0x05b4, "hiriq"},
+ {0x05b4, "hiriq14"},
+ {0x05b4, "hiriq21"},
+ {0x05b4, "hiriq2d"},
+ {0x05b4, "hiriqhebrew"},
+ {0x05b4, "hiriqnarrowhebrew"},
+ {0x05b4, "hiriqquarterhebrew"},
+ {0x05b4, "hiriqwidehebrew"},
+ {0x1e96, "hlinebelow"},
+ {0xff48, "hmonospace"},
+ {0x0570, "hoarmenian"},
+ {0x0e2b, "hohipthai"},
+ {0x307b, "hohiragana"},
+ {0x30db, "hokatakana"},
+ {0xff8e, "hokatakanahalfwidth"},
+ {0x05b9, "holam"},
+ {0x05b9, "holam19"},
+ {0x05b9, "holam26"},
+ {0x05b9, "holam32"},
+ {0x05b9, "holamhebrew"},
+ {0x05b9, "holamnarrowhebrew"},
+ {0x05b9, "holamquarterhebrew"},
+ {0x05b9, "holamwidehebrew"},
+ {0x0e2e, "honokhukthai"},
{0x0309, "hookabovecomb"},
+ {0x0309, "hookcmb"},
+ {0x0321, "hookpalatalizedbelowcmb"},
+ {0x0322, "hookretroflexbelowcmb"},
+ {0x3342, "hoonsquare"},
+ {0x03e9, "horicoptic"},
+ {0x2015, "horizontalbar"},
+ {0x031b, "horncmb"},
+ {0x2668, "hotsprings"},
{0x2302, "house"},
+ {0x24a3, "hparen"},
+ {0x02b0, "hsuperior"},
+ {0x0265, "hturned"},
+ {0x3075, "huhiragana"},
+ {0x3333, "huiitosquare"},
+ {0x30d5, "hukatakana"},
+ {0xff8c, "hukatakanahalfwidth"},
{0x02dd, "hungarumlaut"},
+ {0x030b, "hungarumlautcmb"},
+ {0x0195, "hv"},
{0x002d, "hyphen"},
{0xf6e5, "hypheninferior"},
+ {0xff0d, "hyphenmonospace"},
+ {0xfe63, "hyphensmall"},
{0xf6e6, "hyphensuperior"},
+ {0x2010, "hyphentwo"},
{0x0069, "i"},
{0x00ed, "iacute"},
+ {0x044f, "iacyrillic"},
+ {0x0987, "ibengali"},
+ {0x3127, "ibopomofo"},
{0x012d, "ibreve"},
+ {0x01d0, "icaron"},
+ {0x24d8, "icircle"},
{0x00ee, "icircumflex"},
+ {0x0456, "icyrillic"},
+ {0x0209, "idblgrave"},
+ {0x328f, "ideographearthcircle"},
+ {0x328b, "ideographfirecircle"},
+ {0x323f, "ideographicallianceparen"},
+ {0x323a, "ideographiccallparen"},
+ {0x32a5, "ideographiccentrecircle"},
+ {0x3006, "ideographicclose"},
+ {0x3001, "ideographiccomma"},
+ {0xff64, "ideographiccommaleft"},
+ {0x3237, "ideographiccongratulationparen"},
+ {0x32a3, "ideographiccorrectcircle"},
+ {0x322f, "ideographicearthparen"},
+ {0x323d, "ideographicenterpriseparen"},
+ {0x329d, "ideographicexcellentcircle"},
+ {0x3240, "ideographicfestivalparen"},
+ {0x3296, "ideographicfinancialcircle"},
+ {0x3236, "ideographicfinancialparen"},
+ {0x322b, "ideographicfireparen"},
+ {0x3232, "ideographichaveparen"},
+ {0x32a4, "ideographichighcircle"},
+ {0x3005, "ideographiciterationmark"},
+ {0x3298, "ideographiclaborcircle"},
+ {0x3238, "ideographiclaborparen"},
+ {0x32a7, "ideographicleftcircle"},
+ {0x32a6, "ideographiclowcircle"},
+ {0x32a9, "ideographicmedicinecircle"},
+ {0x322e, "ideographicmetalparen"},
+ {0x322a, "ideographicmoonparen"},
+ {0x3234, "ideographicnameparen"},
+ {0x3002, "ideographicperiod"},
+ {0x329e, "ideographicprintcircle"},
+ {0x3243, "ideographicreachparen"},
+ {0x3239, "ideographicrepresentparen"},
+ {0x323e, "ideographicresourceparen"},
+ {0x32a8, "ideographicrightcircle"},
+ {0x3299, "ideographicsecretcircle"},
+ {0x3242, "ideographicselfparen"},
+ {0x3233, "ideographicsocietyparen"},
+ {0x3000, "ideographicspace"},
+ {0x3235, "ideographicspecialparen"},
+ {0x3231, "ideographicstockparen"},
+ {0x323b, "ideographicstudyparen"},
+ {0x3230, "ideographicsunparen"},
+ {0x323c, "ideographicsuperviseparen"},
+ {0x322c, "ideographicwaterparen"},
+ {0x322d, "ideographicwoodparen"},
+ {0x3007, "ideographiczero"},
+ {0x328e, "ideographmetalcircle"},
+ {0x328a, "ideographmooncircle"},
+ {0x3294, "ideographnamecircle"},
+ {0x3290, "ideographsuncircle"},
+ {0x328c, "ideographwatercircle"},
+ {0x328d, "ideographwoodcircle"},
+ {0x0907, "ideva"},
{0x00ef, "idieresis"},
+ {0x1e2f, "idieresisacute"},
+ {0x04e5, "idieresiscyrillic"},
+ {0x1ecb, "idotbelow"},
+ {0x04d7, "iebrevecyrillic"},
+ {0x0435, "iecyrillic"},
+ {0x3275, "ieungacirclekorean"},
+ {0x3215, "ieungaparenkorean"},
+ {0x3267, "ieungcirclekorean"},
+ {0x3147, "ieungkorean"},
+ {0x3207, "ieungparenkorean"},
{0x00ec, "igrave"},
+ {0x0a87, "igujarati"},
+ {0x0a07, "igurmukhi"},
+ {0x3044, "ihiragana"},
+ {0x1ec9, "ihookabove"},
+ {0x0988, "iibengali"},
+ {0x0438, "iicyrillic"},
+ {0x0908, "iideva"},
+ {0x0a88, "iigujarati"},
+ {0x0a08, "iigurmukhi"},
+ {0x0a40, "iimatragurmukhi"},
+ {0x020b, "iinvertedbreve"},
+ {0x0439, "iishortcyrillic"},
+ {0x09c0, "iivowelsignbengali"},
+ {0x0940, "iivowelsigndeva"},
+ {0x0ac0, "iivowelsigngujarati"},
{0x0133, "ij"},
+ {0x30a4, "ikatakana"},
+ {0xff72, "ikatakanahalfwidth"},
+ {0x3163, "ikorean"},
+ {0x02dc, "ilde"},
+ {0x05ac, "iluyhebrew"},
{0x012b, "imacron"},
+ {0x04e3, "imacroncyrillic"},
+ {0x2253, "imageorapproximatelyequal"},
+ {0x0a3f, "imatragurmukhi"},
+ {0xff49, "imonospace"},
+ {0x2206, "increment"},
{0x221e, "infinity"},
+ {0x056b, "iniarmenian"},
{0x222b, "integral"},
+ {0x2321, "integralbottom"},
{0x2321, "integralbt"},
{0xf8f5, "integralex"},
+ {0x2320, "integraltop"},
{0x2320, "integraltp"},
{0x2229, "intersection"},
+ {0x3305, "intisquare"},
{0x25d8, "invbullet"},
{0x25d9, "invcircle"},
{0x263b, "invsmileface"},
+ {0x0451, "iocyrillic"},
{0x012f, "iogonek"},
{0x03b9, "iota"},
{0x03ca, "iotadieresis"},
{0x0390, "iotadieresistonos"},
+ {0x0269, "iotalatin"},
{0x03af, "iotatonos"},
+ {0x24a4, "iparen"},
+ {0x0a72, "irigurmukhi"},
+ {0x3043, "ismallhiragana"},
+ {0x30a3, "ismallkatakana"},
+ {0xff68, "ismallkatakanahalfwidth"},
+ {0x09fa, "issharbengali"},
+ {0x0268, "istroke"},
{0xf6ed, "isuperior"},
+ {0x309d, "iterationhiragana"},
+ {0x30fd, "iterationkatakana"},
{0x0129, "itilde"},
+ {0x1e2d, "itildebelow"},
+ {0x3129, "iubopomofo"},
+ {0x044e, "iucyrillic"},
+ {0x09bf, "ivowelsignbengali"},
+ {0x093f, "ivowelsigndeva"},
+ {0x0abf, "ivowelsigngujarati"},
+ {0x0475, "izhitsacyrillic"},
+ {0x0477, "izhitsadblgravecyrillic"},
{0x006a, "j"},
+ {0x0571, "jaarmenian"},
+ {0x099c, "jabengali"},
+ {0x091c, "jadeva"},
+ {0x0a9c, "jagujarati"},
+ {0x0a1c, "jagurmukhi"},
+ {0x3110, "jbopomofo"},
+ {0x01f0, "jcaron"},
+ {0x24d9, "jcircle"},
{0x0135, "jcircumflex"},
+ {0x029d, "jcrossedtail"},
+ {0x025f, "jdotlessstroke"},
+ {0x0458, "jecyrillic"},
+ {0x062c, "jeemarabic"},
+ {0xfe9e, "jeemfinalarabic"},
+ {0xfe9f, "jeeminitialarabic"},
+ {0xfea0, "jeemmedialarabic"},
+ {0x0698, "jeharabic"},
+ {0xfb8b, "jehfinalarabic"},
+ {0x099d, "jhabengali"},
+ {0x091d, "jhadeva"},
+ {0x0a9d, "jhagujarati"},
+ {0x0a1d, "jhagurmukhi"},
+ {0x057b, "jheharmenian"},
+ {0x3004, "jis"},
+ {0xff4a, "jmonospace"},
+ {0x24a5, "jparen"},
+ {0x02b2, "jsuperior"},
{0x006b, "k"},
+ {0x04a1, "kabashkircyrillic"},
+ {0x0995, "kabengali"},
+ {0x1e31, "kacute"},
+ {0x043a, "kacyrillic"},
+ {0x049b, "kadescendercyrillic"},
+ {0x0915, "kadeva"},
+ {0x05db, "kaf"},
+ {0x0643, "kafarabic"},
+ {0xfb3b, "kafdagesh"},
+ {0xfb3b, "kafdageshhebrew"},
+ {0xfeda, "kaffinalarabic"},
+ {0x05db, "kafhebrew"},
+ {0xfedb, "kafinitialarabic"},
+ {0xfedc, "kafmedialarabic"},
+ {0xfb4d, "kafrafehebrew"},
+ {0x0a95, "kagujarati"},
+ {0x0a15, "kagurmukhi"},
+ {0x304b, "kahiragana"},
+ {0x04c4, "kahookcyrillic"},
+ {0x30ab, "kakatakana"},
+ {0xff76, "kakatakanahalfwidth"},
{0x03ba, "kappa"},
+ {0x03f0, "kappasymbolgreek"},
+ {0x3171, "kapyeounmieumkorean"},
+ {0x3184, "kapyeounphieuphkorean"},
+ {0x3178, "kapyeounpieupkorean"},
+ {0x3179, "kapyeounssangpieupkorean"},
+ {0x330d, "karoriisquare"},
+ {0x0640, "kashidaautoarabic"},
+ {0x0640, "kashidaautonosidebearingarabic"},
+ {0x30f5, "kasmallkatakana"},
+ {0x3384, "kasquare"},
+ {0x0650, "kasraarabic"},
+ {0x064d, "kasratanarabic"},
+ {0x049f, "kastrokecyrillic"},
+ {0xff70, "katahiraprolongmarkhalfwidth"},
+ {0x049d, "kaverticalstrokecyrillic"},
+ {0x310e, "kbopomofo"},
+ {0x3389, "kcalsquare"},
+ {0x01e9, "kcaron"},
+ {0x0137, "kcedilla"},
+ {0x24da, "kcircle"},
{0x0137, "kcommaaccent"},
+ {0x1e33, "kdotbelow"},
+ {0x0584, "keharmenian"},
+ {0x3051, "kehiragana"},
+ {0x30b1, "kekatakana"},
+ {0xff79, "kekatakanahalfwidth"},
+ {0x056f, "kenarmenian"},
+ {0x30f6, "kesmallkatakana"},
{0x0138, "kgreenlandic"},
+ {0x0996, "khabengali"},
+ {0x0445, "khacyrillic"},
+ {0x0916, "khadeva"},
+ {0x0a96, "khagujarati"},
+ {0x0a16, "khagurmukhi"},
+ {0x062e, "khaharabic"},
+ {0xfea6, "khahfinalarabic"},
+ {0xfea7, "khahinitialarabic"},
+ {0xfea8, "khahmedialarabic"},
+ {0x03e7, "kheicoptic"},
+ {0x0959, "khhadeva"},
+ {0x0a59, "khhagurmukhi"},
+ {0x3278, "khieukhacirclekorean"},
+ {0x3218, "khieukhaparenkorean"},
+ {0x326a, "khieukhcirclekorean"},
+ {0x314b, "khieukhkorean"},
+ {0x320a, "khieukhparenkorean"},
+ {0x0e02, "khokhaithai"},
+ {0x0e05, "khokhonthai"},
+ {0x0e03, "khokhuatthai"},
+ {0x0e04, "khokhwaithai"},
+ {0x0e5b, "khomutthai"},
+ {0x0199, "khook"},
+ {0x0e06, "khorakhangthai"},
+ {0x3391, "khzsquare"},
+ {0x304d, "kihiragana"},
+ {0x30ad, "kikatakana"},
+ {0xff77, "kikatakanahalfwidth"},
+ {0x3315, "kiroguramusquare"},
+ {0x3316, "kiromeetorusquare"},
+ {0x3314, "kirosquare"},
+ {0x326e, "kiyeokacirclekorean"},
+ {0x320e, "kiyeokaparenkorean"},
+ {0x3260, "kiyeokcirclekorean"},
+ {0x3131, "kiyeokkorean"},
+ {0x3200, "kiyeokparenkorean"},
+ {0x3133, "kiyeoksioskorean"},
+ {0x045c, "kjecyrillic"},
+ {0x1e35, "klinebelow"},
+ {0x3398, "klsquare"},
+ {0x33a6, "kmcubedsquare"},
+ {0xff4b, "kmonospace"},
+ {0x33a2, "kmsquaredsquare"},
+ {0x3053, "kohiragana"},
+ {0x33c0, "kohmsquare"},
+ {0x0e01, "kokaithai"},
+ {0x30b3, "kokatakana"},
+ {0xff7a, "kokatakanahalfwidth"},
+ {0x331e, "kooposquare"},
+ {0x0481, "koppacyrillic"},
+ {0x327f, "koreanstandardsymbol"},
+ {0x0343, "koroniscmb"},
+ {0x24a6, "kparen"},
+ {0x33aa, "kpasquare"},
+ {0x046f, "ksicyrillic"},
+ {0x33cf, "ktsquare"},
+ {0x029e, "kturned"},
+ {0x304f, "kuhiragana"},
+ {0x30af, "kukatakana"},
+ {0xff78, "kukatakanahalfwidth"},
+ {0x33b8, "kvsquare"},
+ {0x33be, "kwsquare"},
{0x006c, "l"},
+ {0x09b2, "labengali"},
{0x013a, "lacute"},
+ {0x0932, "ladeva"},
+ {0x0ab2, "lagujarati"},
+ {0x0a32, "lagurmukhi"},
+ {0x0e45, "lakkhangyaothai"},
+ {0xfefc, "lamaleffinalarabic"},
+ {0xfef8, "lamalefhamzaabovefinalarabic"},
+ {0xfef7, "lamalefhamzaaboveisolatedarabic"},
+ {0xfefa, "lamalefhamzabelowfinalarabic"},
+ {0xfef9, "lamalefhamzabelowisolatedarabic"},
+ {0xfefb, "lamalefisolatedarabic"},
+ {0xfef6, "lamalefmaddaabovefinalarabic"},
+ {0xfef5, "lamalefmaddaaboveisolatedarabic"},
+ {0x0644, "lamarabic"},
{0x03bb, "lambda"},
+ {0x019b, "lambdastroke"},
+ {0x05dc, "lamed"},
+ {0xfb3c, "lameddagesh"},
+ {0xfb3c, "lameddageshhebrew"},
+ {0x05dc, "lamedhebrew"},
+ {0xfede, "lamfinalarabic"},
+ {0xfcca, "lamhahinitialarabic"},
+ {0xfedf, "laminitialarabic"},
+ {0xfcc9, "lamjeeminitialarabic"},
+ {0xfccb, "lamkhahinitialarabic"},
+ {0xfdf2, "lamlamhehisolatedarabic"},
+ {0xfee0, "lammedialarabic"},
+ {0xfd88, "lammeemhahinitialarabic"},
+ {0xfccc, "lammeeminitialarabic"},
+ {0x25ef, "largecircle"},
+ {0x019a, "lbar"},
+ {0x026c, "lbelt"},
+ {0x310c, "lbopomofo"},
{0x013e, "lcaron"},
+ {0x013c, "lcedilla"},
+ {0x24db, "lcircle"},
+ {0x1e3d, "lcircumflexbelow"},
{0x013c, "lcommaaccent"},
{0x0140, "ldot"},
+ {0x0140, "ldotaccent"},
+ {0x1e37, "ldotbelow"},
+ {0x1e39, "ldotbelowmacron"},
+ {0x031a, "leftangleabovecmb"},
+ {0x0318, "lefttackbelowcmb"},
{0x003c, "less"},
{0x2264, "lessequal"},
+ {0x22da, "lessequalorgreater"},
+ {0xff1c, "lessmonospace"},
+ {0x2272, "lessorequivalent"},
+ {0x2276, "lessorgreater"},
+ {0x2266, "lessoverequal"},
+ {0xfe64, "lesssmall"},
+ {0x026e, "lezh"},
{0x258c, "lfblock"},
+ {0x026d, "lhookretroflex"},
{0x20a4, "lira"},
+ {0x056c, "liwnarmenian"},
+ {0x01c9, "lj"},
+ {0x0459, "ljecyrillic"},
{0xf6c0, "ll"},
+ {0x0933, "lladeva"},
+ {0x0ab3, "llagujarati"},
+ {0x1e3b, "llinebelow"},
+ {0x0934, "llladeva"},
+ {0x09e1, "llvocalicbengali"},
+ {0x0961, "llvocalicdeva"},
+ {0x09e3, "llvocalicvowelsignbengali"},
+ {0x0963, "llvocalicvowelsigndeva"},
+ {0x026b, "lmiddletilde"},
+ {0xff4c, "lmonospace"},
+ {0x33d0, "lmsquare"},
+ {0x0e2c, "lochulathai"},
{0x2227, "logicaland"},
{0x00ac, "logicalnot"},
+ {0x2310, "logicalnotreversed"},
{0x2228, "logicalor"},
+ {0x0e25, "lolingthai"},
{0x017f, "longs"},
+ {0xfe4e, "lowlinecenterline"},
+ {0x0332, "lowlinecmb"},
+ {0xfe4d, "lowlinedashed"},
{0x25ca, "lozenge"},
+ {0x24a7, "lparen"},
{0x0142, "lslash"},
+ {0x2113, "lsquare"},
{0xf6ee, "lsuperior"},
{0x2591, "ltshade"},
+ {0x0e26, "luthai"},
+ {0x098c, "lvocalicbengali"},
+ {0x090c, "lvocalicdeva"},
+ {0x09e2, "lvocalicvowelsignbengali"},
+ {0x0962, "lvocalicvowelsigndeva"},
+ {0x33d3, "lxsquare"},
{0x006d, "m"},
+ {0x09ae, "mabengali"},
{0x00af, "macron"},
+ {0x0331, "macronbelowcmb"},
+ {0x0304, "macroncmb"},
+ {0x02cd, "macronlowmod"},
+ {0xffe3, "macronmonospace"},
+ {0x1e3f, "macute"},
+ {0x092e, "madeva"},
+ {0x0aae, "magujarati"},
+ {0x0a2e, "magurmukhi"},
+ {0x05a4, "mahapakhhebrew"},
+ {0x05a4, "mahapakhlefthebrew"},
+ {0x307e, "mahiragana"},
+ {0xf895, "maichattawalowleftthai"},
+ {0xf894, "maichattawalowrightthai"},
+ {0x0e4b, "maichattawathai"},
+ {0xf893, "maichattawaupperleftthai"},
+ {0xf88c, "maieklowleftthai"},
+ {0xf88b, "maieklowrightthai"},
+ {0x0e48, "maiekthai"},
+ {0xf88a, "maiekupperleftthai"},
+ {0xf884, "maihanakatleftthai"},
+ {0x0e31, "maihanakatthai"},
+ {0xf889, "maitaikhuleftthai"},
+ {0x0e47, "maitaikhuthai"},
+ {0xf88f, "maitholowleftthai"},
+ {0xf88e, "maitholowrightthai"},
+ {0x0e49, "maithothai"},
+ {0xf88d, "maithoupperleftthai"},
+ {0xf892, "maitrilowleftthai"},
+ {0xf891, "maitrilowrightthai"},
+ {0x0e4a, "maitrithai"},
+ {0xf890, "maitriupperleftthai"},
+ {0x0e46, "maiyamokthai"},
+ {0x30de, "makatakana"},
+ {0xff8f, "makatakanahalfwidth"},
{0x2642, "male"},
+ {0x3347, "mansyonsquare"},
+ {0x05be, "maqafhebrew"},
+ {0x2642, "mars"},
+ {0x05af, "masoracirclehebrew"},
+ {0x3383, "masquare"},
+ {0x3107, "mbopomofo"},
+ {0x33d4, "mbsquare"},
+ {0x24dc, "mcircle"},
+ {0x33a5, "mcubedsquare"},
+ {0x1e41, "mdotaccent"},
+ {0x1e43, "mdotbelow"},
+ {0x0645, "meemarabic"},
+ {0xfee2, "meemfinalarabic"},
+ {0xfee3, "meeminitialarabic"},
+ {0xfee4, "meemmedialarabic"},
+ {0xfcd1, "meemmeeminitialarabic"},
+ {0xfc48, "meemmeemisolatedarabic"},
+ {0x334d, "meetorusquare"},
+ {0x3081, "mehiragana"},
+ {0x337e, "meizierasquare"},
+ {0x30e1, "mekatakana"},
+ {0xff92, "mekatakanahalfwidth"},
+ {0x05de, "mem"},
+ {0xfb3e, "memdagesh"},
+ {0xfb3e, "memdageshhebrew"},
+ {0x05de, "memhebrew"},
+ {0x0574, "menarmenian"},
+ {0x05a5, "merkhahebrew"},
+ {0x05a6, "merkhakefulahebrew"},
+ {0x05a6, "merkhakefulalefthebrew"},
+ {0x05a5, "merkhalefthebrew"},
+ {0x0271, "mhook"},
+ {0x3392, "mhzsquare"},
+ {0xff65, "middledotkatakanahalfwidth"},
+ {0x00b7, "middot"},
+ {0x3272, "mieumacirclekorean"},
+ {0x3212, "mieumaparenkorean"},
+ {0x3264, "mieumcirclekorean"},
+ {0x3141, "mieumkorean"},
+ {0x3170, "mieumpansioskorean"},
+ {0x3204, "mieumparenkorean"},
+ {0x316e, "mieumpieupkorean"},
+ {0x316f, "mieumsioskorean"},
+ {0x307f, "mihiragana"},
+ {0x30df, "mikatakana"},
+ {0xff90, "mikatakanahalfwidth"},
{0x2212, "minus"},
+ {0x0320, "minusbelowcmb"},
+ {0x2296, "minuscircle"},
+ {0x02d7, "minusmod"},
+ {0x2213, "minusplus"},
{0x2032, "minute"},
+ {0x334a, "miribaarusquare"},
+ {0x3349, "mirisquare"},
+ {0x0270, "mlonglegturned"},
+ {0x3396, "mlsquare"},
+ {0x33a3, "mmcubedsquare"},
+ {0xff4d, "mmonospace"},
+ {0x339f, "mmsquaredsquare"},
+ {0x3082, "mohiragana"},
+ {0x33c1, "mohmsquare"},
+ {0x30e2, "mokatakana"},
+ {0xff93, "mokatakanahalfwidth"},
+ {0x33d6, "molsquare"},
+ {0x0e21, "momathai"},
+ {0x33a7, "moverssquare"},
+ {0x33a8, "moverssquaredsquare"},
+ {0x24a8, "mparen"},
+ {0x33ab, "mpasquare"},
+ {0x33b3, "mssquare"},
{0xf6ef, "msuperior"},
+ {0x026f, "mturned"},
{0x00b5, "mu"},
+ {0x00b5, "mu1"},
+ {0x3382, "muasquare"},
+ {0x226b, "muchgreater"},
+ {0x226a, "muchless"},
+ {0x338c, "mufsquare"},
+ {0x03bc, "mugreek"},
+ {0x338d, "mugsquare"},
+ {0x3080, "muhiragana"},
+ {0x30e0, "mukatakana"},
+ {0xff91, "mukatakanahalfwidth"},
+ {0x3395, "mulsquare"},
{0x00d7, "multiply"},
+ {0x339b, "mumsquare"},
+ {0x05a3, "munahhebrew"},
+ {0x05a3, "munahlefthebrew"},
{0x266a, "musicalnote"},
{0x266b, "musicalnotedbl"},
+ {0x266d, "musicflatsign"},
+ {0x266f, "musicsharpsign"},
+ {0x33b2, "mussquare"},
+ {0x33b6, "muvsquare"},
+ {0x33bc, "muwsquare"},
+ {0x33b9, "mvmegasquare"},
+ {0x33b7, "mvsquare"},
+ {0x33bf, "mwmegasquare"},
+ {0x33bd, "mwsquare"},
{0x006e, "n"},
+ {0x09a8, "nabengali"},
+ {0x2207, "nabla"},
{0x0144, "nacute"},
+ {0x0928, "nadeva"},
+ {0x0aa8, "nagujarati"},
+ {0x0a28, "nagurmukhi"},
+ {0x306a, "nahiragana"},
+ {0x30ca, "nakatakana"},
+ {0xff85, "nakatakanahalfwidth"},
{0x0149, "napostrophe"},
+ {0x3381, "nasquare"},
+ {0x310b, "nbopomofo"},
{0x00a0, "nbspace"},
{0x0148, "ncaron"},
+ {0x0146, "ncedilla"},
+ {0x24dd, "ncircle"},
+ {0x1e4b, "ncircumflexbelow"},
{0x0146, "ncommaaccent"},
+ {0x1e45, "ndotaccent"},
+ {0x1e47, "ndotbelow"},
+ {0x306d, "nehiragana"},
+ {0x30cd, "nekatakana"},
+ {0xff88, "nekatakanahalfwidth"},
+ {0x20aa, "newsheqelsign"},
+ {0x338b, "nfsquare"},
+ {0x0999, "ngabengali"},
+ {0x0919, "ngadeva"},
+ {0x0a99, "ngagujarati"},
+ {0x0a19, "ngagurmukhi"},
+ {0x0e07, "ngonguthai"},
+ {0x3093, "nhiragana"},
+ {0x0272, "nhookleft"},
+ {0x0273, "nhookretroflex"},
+ {0x326f, "nieunacirclekorean"},
+ {0x320f, "nieunaparenkorean"},
+ {0x3135, "nieuncieuckorean"},
+ {0x3261, "nieuncirclekorean"},
+ {0x3136, "nieunhieuhkorean"},
+ {0x3134, "nieunkorean"},
+ {0x3168, "nieunpansioskorean"},
+ {0x3201, "nieunparenkorean"},
+ {0x3167, "nieunsioskorean"},
+ {0x3166, "nieuntikeutkorean"},
+ {0x306b, "nihiragana"},
+ {0x30cb, "nikatakana"},
+ {0xff86, "nikatakanahalfwidth"},
+ {0xf899, "nikhahitleftthai"},
+ {0x0e4d, "nikhahitthai"},
{0x0039, "nine"},
+ {0x0669, "ninearabic"},
+ {0x09ef, "ninebengali"},
+ {0x2468, "ninecircle"},
+ {0x2792, "ninecircleinversesansserif"},
+ {0x096f, "ninedeva"},
+ {0x0aef, "ninegujarati"},
+ {0x0a6f, "ninegurmukhi"},
+ {0x0669, "ninehackarabic"},
+ {0x3029, "ninehangzhou"},
+ {0x3228, "nineideographicparen"},
{0x2089, "nineinferior"},
+ {0xff19, "ninemonospace"},
{0xf739, "nineoldstyle"},
+ {0x247c, "nineparen"},
+ {0x2490, "nineperiod"},
+ {0x06f9, "ninepersian"},
+ {0x2178, "nineroman"},
{0x2079, "ninesuperior"},
+ {0x2472, "nineteencircle"},
+ {0x2486, "nineteenparen"},
+ {0x249a, "nineteenperiod"},
+ {0x0e59, "ninethai"},
+ {0x01cc, "nj"},
+ {0x045a, "njecyrillic"},
+ {0x30f3, "nkatakana"},
+ {0xff9d, "nkatakanahalfwidth"},
+ {0x019e, "nlegrightlong"},
+ {0x1e49, "nlinebelow"},
+ {0xff4e, "nmonospace"},
+ {0x339a, "nmsquare"},
+ {0x09a3, "nnabengali"},
+ {0x0923, "nnadeva"},
+ {0x0aa3, "nnagujarati"},
+ {0x0a23, "nnagurmukhi"},
+ {0x0929, "nnnadeva"},
+ {0x306e, "nohiragana"},
+ {0x30ce, "nokatakana"},
+ {0xff89, "nokatakanahalfwidth"},
{0x00a0, "nonbreakingspace"},
+ {0x0e13, "nonenthai"},
+ {0x0e19, "nonuthai"},
+ {0x0646, "noonarabic"},
+ {0xfee6, "noonfinalarabic"},
+ {0x06ba, "noonghunnaarabic"},
+ {0xfb9f, "noonghunnafinalarabic"},
+ {0xfee7, "nooninitialarabic"},
+ {0xfcd2, "noonjeeminitialarabic"},
+ {0xfc4b, "noonjeemisolatedarabic"},
+ {0xfee8, "noonmedialarabic"},
+ {0xfcd5, "noonmeeminitialarabic"},
+ {0xfc4e, "noonmeemisolatedarabic"},
+ {0xfc8d, "noonnoonfinalarabic"},
+ {0x220c, "notcontains"},
{0x2209, "notelement"},
+ {0x2209, "notelementof"},
{0x2260, "notequal"},
+ {0x226f, "notgreater"},
+ {0x2271, "notgreaternorequal"},
+ {0x2279, "notgreaternorless"},
+ {0x2262, "notidentical"},
+ {0x226e, "notless"},
+ {0x2270, "notlessnorequal"},
+ {0x2226, "notparallel"},
+ {0x2280, "notprecedes"},
{0x2284, "notsubset"},
+ {0x2281, "notsucceeds"},
+ {0x2285, "notsuperset"},
+ {0x0576, "nowarmenian"},
+ {0x24a9, "nparen"},
+ {0x33b1, "nssquare"},
{0x207f, "nsuperior"},
{0x00f1, "ntilde"},
{0x03bd, "nu"},
+ {0x306c, "nuhiragana"},
+ {0x30cc, "nukatakana"},
+ {0xff87, "nukatakanahalfwidth"},
+ {0x09bc, "nuktabengali"},
+ {0x093c, "nuktadeva"},
+ {0x0abc, "nuktagujarati"},
+ {0x0a3c, "nuktagurmukhi"},
{0x0023, "numbersign"},
+ {0xff03, "numbersignmonospace"},
+ {0xfe5f, "numbersignsmall"},
+ {0x0374, "numeralsigngreek"},
+ {0x0375, "numeralsignlowergreek"},
+ {0x2116, "numero"},
+ {0x05e0, "nun"},
+ {0xfb40, "nundagesh"},
+ {0xfb40, "nundageshhebrew"},
+ {0x05e0, "nunhebrew"},
+ {0x33b5, "nvsquare"},
+ {0x33bb, "nwsquare"},
+ {0x099e, "nyabengali"},
+ {0x091e, "nyadeva"},
+ {0x0a9e, "nyagujarati"},
+ {0x0a1e, "nyagurmukhi"},
{0x006f, "o"},
{0x00f3, "oacute"},
+ {0x0e2d, "oangthai"},
+ {0x0275, "obarred"},
+ {0x04e9, "obarredcyrillic"},
+ {0x04eb, "obarreddieresiscyrillic"},
+ {0x0993, "obengali"},
+ {0x311b, "obopomofo"},
{0x014f, "obreve"},
+ {0x0911, "ocandradeva"},
+ {0x0a91, "ocandragujarati"},
+ {0x0949, "ocandravowelsigndeva"},
+ {0x0ac9, "ocandravowelsigngujarati"},
+ {0x01d2, "ocaron"},
+ {0x24de, "ocircle"},
{0x00f4, "ocircumflex"},
+ {0x1ed1, "ocircumflexacute"},
+ {0x1ed9, "ocircumflexdotbelow"},
+ {0x1ed3, "ocircumflexgrave"},
+ {0x1ed5, "ocircumflexhookabove"},
+ {0x1ed7, "ocircumflextilde"},
+ {0x043e, "ocyrillic"},
+ {0x0151, "odblacute"},
+ {0x020d, "odblgrave"},
+ {0x0913, "odeva"},
{0x00f6, "odieresis"},
+ {0x04e7, "odieresiscyrillic"},
+ {0x1ecd, "odotbelow"},
{0x0153, "oe"},
+ {0x315a, "oekorean"},
{0x02db, "ogonek"},
+ {0x0328, "ogonekcmb"},
{0x00f2, "ograve"},
+ {0x0a93, "ogujarati"},
+ {0x0585, "oharmenian"},
+ {0x304a, "ohiragana"},
+ {0x1ecf, "ohookabove"},
{0x01a1, "ohorn"},
+ {0x1edb, "ohornacute"},
+ {0x1ee3, "ohorndotbelow"},
+ {0x1edd, "ohorngrave"},
+ {0x1edf, "ohornhookabove"},
+ {0x1ee1, "ohorntilde"},
{0x0151, "ohungarumlaut"},
+ {0x01a3, "oi"},
+ {0x020f, "oinvertedbreve"},
+ {0x30aa, "okatakana"},
+ {0xff75, "okatakanahalfwidth"},
+ {0x3157, "okorean"},
+ {0x05ab, "olehebrew"},
{0x014d, "omacron"},
+ {0x1e53, "omacronacute"},
+ {0x1e51, "omacrongrave"},
+ {0x0950, "omdeva"},
{0x03c9, "omega"},
{0x03d6, "omega1"},
+ {0x0461, "omegacyrillic"},
+ {0x0277, "omegalatinclosed"},
+ {0x047b, "omegaroundcyrillic"},
+ {0x047d, "omegatitlocyrillic"},
{0x03ce, "omegatonos"},
+ {0x0ad0, "omgujarati"},
{0x03bf, "omicron"},
{0x03cc, "omicrontonos"},
+ {0xff4f, "omonospace"},
{0x0031, "one"},
+ {0x0661, "onearabic"},
+ {0x09e7, "onebengali"},
+ {0x2460, "onecircle"},
+ {0x278a, "onecircleinversesansserif"},
+ {0x0967, "onedeva"},
{0x2024, "onedotenleader"},
{0x215b, "oneeighth"},
{0xf6dc, "onefitted"},
+ {0x0ae7, "onegujarati"},
+ {0x0a67, "onegurmukhi"},
+ {0x0661, "onehackarabic"},
{0x00bd, "onehalf"},
+ {0x3021, "onehangzhou"},
+ {0x3220, "oneideographicparen"},
{0x2081, "oneinferior"},
+ {0xff11, "onemonospace"},
+ {0x09f4, "onenumeratorbengali"},
{0xf731, "oneoldstyle"},
+ {0x2474, "oneparen"},
+ {0x2488, "oneperiod"},
+ {0x06f1, "onepersian"},
{0x00bc, "onequarter"},
+ {0x2170, "oneroman"},
{0x00b9, "onesuperior"},
+ {0x0e51, "onethai"},
{0x2153, "onethird"},
+ {0x01eb, "oogonek"},
+ {0x01ed, "oogonekmacron"},
+ {0x0a13, "oogurmukhi"},
+ {0x0a4b, "oomatragurmukhi"},
+ {0x0254, "oopen"},
+ {0x24aa, "oparen"},
{0x25e6, "openbullet"},
+ {0x2325, "option"},
{0x00aa, "ordfeminine"},
{0x00ba, "ordmasculine"},
{0x221f, "orthogonal"},
+ {0x0912, "oshortdeva"},
+ {0x094a, "oshortvowelsigndeva"},
{0x00f8, "oslash"},
{0x01ff, "oslashacute"},
+ {0x3049, "osmallhiragana"},
+ {0x30a9, "osmallkatakana"},
+ {0xff6b, "osmallkatakanahalfwidth"},
+ {0x01ff, "ostrokeacute"},
{0xf6f0, "osuperior"},
+ {0x047f, "otcyrillic"},
{0x00f5, "otilde"},
+ {0x1e4d, "otildeacute"},
+ {0x1e4f, "otildedieresis"},
+ {0x3121, "oubopomofo"},
+ {0x203e, "overline"},
+ {0xfe4a, "overlinecenterline"},
+ {0x0305, "overlinecmb"},
+ {0xfe49, "overlinedashed"},
+ {0xfe4c, "overlinedblwavy"},
+ {0xfe4b, "overlinewavy"},
+ {0x00af, "overscore"},
+ {0x09cb, "ovowelsignbengali"},
+ {0x094b, "ovowelsigndeva"},
+ {0x0acb, "ovowelsigngujarati"},
{0x0070, "p"},
+ {0x3380, "paampssquare"},
+ {0x332b, "paasentosquare"},
+ {0x09aa, "pabengali"},
+ {0x1e55, "pacute"},
+ {0x092a, "padeva"},
+ {0x21df, "pagedown"},
+ {0x21de, "pageup"},
+ {0x0aaa, "pagujarati"},
+ {0x0a2a, "pagurmukhi"},
+ {0x3071, "pahiragana"},
+ {0x0e2f, "paiyannoithai"},
+ {0x30d1, "pakatakana"},
+ {0x0484, "palatalizationcyrilliccmb"},
+ {0x04c0, "palochkacyrillic"},
+ {0x317f, "pansioskorean"},
{0x00b6, "paragraph"},
+ {0x2225, "parallel"},
{0x0028, "parenleft"},
+ {0xfd3e, "parenleftaltonearabic"},
{0xf8ed, "parenleftbt"},
{0xf8ec, "parenleftex"},
{0x208d, "parenleftinferior"},
+ {0xff08, "parenleftmonospace"},
+ {0xfe59, "parenleftsmall"},
{0x207d, "parenleftsuperior"},
{0xf8eb, "parenlefttp"},
+ {0xfe35, "parenleftvertical"},
{0x0029, "parenright"},
+ {0xfd3f, "parenrightaltonearabic"},
{0xf8f8, "parenrightbt"},
{0xf8f7, "parenrightex"},
{0x208e, "parenrightinferior"},
+ {0xff09, "parenrightmonospace"},
+ {0xfe5a, "parenrightsmall"},
{0x207e, "parenrightsuperior"},
{0xf8f6, "parenrighttp"},
+ {0xfe36, "parenrightvertical"},
{0x2202, "partialdiff"},
+ {0x05c0, "paseqhebrew"},
+ {0x0599, "pashtahebrew"},
+ {0x33a9, "pasquare"},
+ {0x05b7, "patah"},
+ {0x05b7, "patah11"},
+ {0x05b7, "patah1d"},
+ {0x05b7, "patah2a"},
+ {0x05b7, "patahhebrew"},
+ {0x05b7, "patahnarrowhebrew"},
+ {0x05b7, "patahquarterhebrew"},
+ {0x05b7, "patahwidehebrew"},
+ {0x05a1, "pazerhebrew"},
+ {0x3106, "pbopomofo"},
+ {0x24df, "pcircle"},
+ {0x1e57, "pdotaccent"},
+ {0x05e4, "pe"},
+ {0x043f, "pecyrillic"},
+ {0xfb44, "pedagesh"},
+ {0xfb44, "pedageshhebrew"},
+ {0x333b, "peezisquare"},
+ {0xfb43, "pefinaldageshhebrew"},
+ {0x067e, "peharabic"},
+ {0x057a, "peharmenian"},
+ {0x05e4, "pehebrew"},
+ {0xfb57, "pehfinalarabic"},
+ {0xfb58, "pehinitialarabic"},
+ {0x307a, "pehiragana"},
+ {0xfb59, "pehmedialarabic"},
+ {0x30da, "pekatakana"},
+ {0x04a7, "pemiddlehookcyrillic"},
+ {0xfb4e, "perafehebrew"},
{0x0025, "percent"},
+ {0x066a, "percentarabic"},
+ {0xff05, "percentmonospace"},
+ {0xfe6a, "percentsmall"},
{0x002e, "period"},
+ {0x0589, "periodarmenian"},
{0x00b7, "periodcentered"},
+ {0xff61, "periodhalfwidth"},
{0xf6e7, "periodinferior"},
+ {0xff0e, "periodmonospace"},
+ {0xfe52, "periodsmall"},
{0xf6e8, "periodsuperior"},
+ {0x0342, "perispomenigreekcmb"},
{0x22a5, "perpendicular"},
{0x2030, "perthousand"},
{0x20a7, "peseta"},
+ {0x338a, "pfsquare"},
+ {0x09ab, "phabengali"},
+ {0x092b, "phadeva"},
+ {0x0aab, "phagujarati"},
+ {0x0a2b, "phagurmukhi"},
{0x03c6, "phi"},
{0x03d5, "phi1"},
+ {0x327a, "phieuphacirclekorean"},
+ {0x321a, "phieuphaparenkorean"},
+ {0x326c, "phieuphcirclekorean"},
+ {0x314d, "phieuphkorean"},
+ {0x320c, "phieuphparenkorean"},
+ {0x0278, "philatin"},
+ {0x0e3a, "phinthuthai"},
+ {0x03d5, "phisymbolgreek"},
+ {0x01a5, "phook"},
+ {0x0e1e, "phophanthai"},
+ {0x0e1c, "phophungthai"},
+ {0x0e20, "phosamphaothai"},
{0x03c0, "pi"},
+ {0x3273, "pieupacirclekorean"},
+ {0x3213, "pieupaparenkorean"},
+ {0x3176, "pieupcieuckorean"},
+ {0x3265, "pieupcirclekorean"},
+ {0x3172, "pieupkiyeokkorean"},
+ {0x3142, "pieupkorean"},
+ {0x3205, "pieupparenkorean"},
+ {0x3174, "pieupsioskiyeokkorean"},
+ {0x3144, "pieupsioskorean"},
+ {0x3175, "pieupsiostikeutkorean"},
+ {0x3177, "pieupthieuthkorean"},
+ {0x3173, "pieuptikeutkorean"},
+ {0x3074, "pihiragana"},
+ {0x30d4, "pikatakana"},
+ {0x03d6, "pisymbolgreek"},
+ {0x0583, "piwrarmenian"},
{0x002b, "plus"},
+ {0x031f, "plusbelowcmb"},
+ {0x2295, "pluscircle"},
{0x00b1, "plusminus"},
+ {0x02d6, "plusmod"},
+ {0xff0b, "plusmonospace"},
+ {0xfe62, "plussmall"},
+ {0x207a, "plussuperior"},
+ {0xff50, "pmonospace"},
+ {0x33d8, "pmsquare"},
+ {0x307d, "pohiragana"},
+ {0x261f, "pointingindexdownwhite"},
+ {0x261c, "pointingindexleftwhite"},
+ {0x261e, "pointingindexrightwhite"},
+ {0x261d, "pointingindexupwhite"},
+ {0x30dd, "pokatakana"},
+ {0x0e1b, "poplathai"},
+ {0x3012, "postalmark"},
+ {0x3020, "postalmarkface"},
+ {0x24ab, "pparen"},
+ {0x227a, "precedes"},
{0x211e, "prescription"},
+ {0x02b9, "primemod"},
+ {0x2035, "primereversed"},
{0x220f, "product"},
+ {0x2305, "projective"},
+ {0x30fc, "prolongedkana"},
+ {0x2318, "propellor"},
{0x2282, "propersubset"},
{0x2283, "propersuperset"},
+ {0x2237, "proportion"},
{0x221d, "proportional"},
{0x03c8, "psi"},
+ {0x0471, "psicyrillic"},
+ {0x0486, "psilipneumatacyrilliccmb"},
+ {0x33b0, "pssquare"},
+ {0x3077, "puhiragana"},
+ {0x30d7, "pukatakana"},
+ {0x33b4, "pvsquare"},
+ {0x33ba, "pwsquare"},
{0x0071, "q"},
+ {0x0958, "qadeva"},
+ {0x05a8, "qadmahebrew"},
+ {0x0642, "qafarabic"},
+ {0xfed6, "qaffinalarabic"},
+ {0xfed7, "qafinitialarabic"},
+ {0xfed8, "qafmedialarabic"},
+ {0x05b8, "qamats"},
+ {0x05b8, "qamats10"},
+ {0x05b8, "qamats1a"},
+ {0x05b8, "qamats1c"},
+ {0x05b8, "qamats27"},
+ {0x05b8, "qamats29"},
+ {0x05b8, "qamats33"},
+ {0x05b8, "qamatsde"},
+ {0x05b8, "qamatshebrew"},
+ {0x05b8, "qamatsnarrowhebrew"},
+ {0x05b8, "qamatsqatanhebrew"},
+ {0x05b8, "qamatsqatannarrowhebrew"},
+ {0x05b8, "qamatsqatanquarterhebrew"},
+ {0x05b8, "qamatsqatanwidehebrew"},
+ {0x05b8, "qamatsquarterhebrew"},
+ {0x05b8, "qamatswidehebrew"},
+ {0x059f, "qarneyparahebrew"},
+ {0x3111, "qbopomofo"},
+ {0x24e0, "qcircle"},
+ {0x02a0, "qhook"},
+ {0xff51, "qmonospace"},
+ {0x05e7, "qof"},
+ {0xfb47, "qofdagesh"},
+ {0xfb47, "qofdageshhebrew"},
+ {0x05e7, "qofhebrew"},
+ {0x24ac, "qparen"},
+ {0x2669, "quarternote"},
+ {0x05bb, "qubuts"},
+ {0x05bb, "qubuts18"},
+ {0x05bb, "qubuts25"},
+ {0x05bb, "qubuts31"},
+ {0x05bb, "qubutshebrew"},
+ {0x05bb, "qubutsnarrowhebrew"},
+ {0x05bb, "qubutsquarterhebrew"},
+ {0x05bb, "qubutswidehebrew"},
{0x003f, "question"},
+ {0x061f, "questionarabic"},
+ {0x055e, "questionarmenian"},
{0x00bf, "questiondown"},
{0xf7bf, "questiondownsmall"},
+ {0x037e, "questiongreek"},
+ {0xff1f, "questionmonospace"},
{0xf73f, "questionsmall"},
{0x0022, "quotedbl"},
{0x201e, "quotedblbase"},
{0x201c, "quotedblleft"},
+ {0xff02, "quotedblmonospace"},
+ {0x301e, "quotedblprime"},
+ {0x301d, "quotedblprimereversed"},
{0x201d, "quotedblright"},
{0x2018, "quoteleft"},
+ {0x201b, "quoteleftreversed"},
{0x201b, "quotereversed"},
{0x2019, "quoteright"},
+ {0x0149, "quoterightn"},
{0x201a, "quotesinglbase"},
{0x0027, "quotesingle"},
+ {0xff07, "quotesinglemonospace"},
{0x0072, "r"},
+ {0x057c, "raarmenian"},
+ {0x09b0, "rabengali"},
{0x0155, "racute"},
+ {0x0930, "radeva"},
{0x221a, "radical"},
{0xf8e5, "radicalex"},
+ {0x33ae, "radoverssquare"},
+ {0x33af, "radoverssquaredsquare"},
+ {0x33ad, "radsquare"},
+ {0x05bf, "rafe"},
+ {0x05bf, "rafehebrew"},
+ {0x0ab0, "ragujarati"},
+ {0x0a30, "ragurmukhi"},
+ {0x3089, "rahiragana"},
+ {0x30e9, "rakatakana"},
+ {0xff97, "rakatakanahalfwidth"},
+ {0x09f1, "ralowerdiagonalbengali"},
+ {0x09f0, "ramiddlediagonalbengali"},
+ {0x0264, "ramshorn"},
+ {0x2236, "ratio"},
+ {0x3116, "rbopomofo"},
{0x0159, "rcaron"},
+ {0x0157, "rcedilla"},
+ {0x24e1, "rcircle"},
{0x0157, "rcommaaccent"},
+ {0x0211, "rdblgrave"},
+ {0x1e59, "rdotaccent"},
+ {0x1e5b, "rdotbelow"},
+ {0x1e5d, "rdotbelowmacron"},
+ {0x203b, "referencemark"},
{0x2286, "reflexsubset"},
{0x2287, "reflexsuperset"},
{0x00ae, "registered"},
{0x00ae, "registersans"},
{0x00ae, "registerserif"},
+ {0x0631, "reharabic"},
+ {0x0580, "reharmenian"},
+ {0xfeae, "rehfinalarabic"},
+ {0x308c, "rehiragana"},
+ {0x30ec, "rekatakana"},
+ {0xff9a, "rekatakanahalfwidth"},
+ {0x05e8, "resh"},
+ {0xfb48, "reshdageshhebrew"},
+ {0x05e8, "reshhebrew"},
+ {0x223d, "reversedtilde"},
+ {0x0597, "reviahebrew"},
+ {0x0597, "reviamugrashhebrew"},
{0x2310, "revlogicalnot"},
+ {0x027e, "rfishhook"},
+ {0x027f, "rfishhookreversed"},
+ {0x09dd, "rhabengali"},
+ {0x095d, "rhadeva"},
{0x03c1, "rho"},
+ {0x027d, "rhook"},
+ {0x027b, "rhookturned"},
+ {0x02b5, "rhookturnedsuperior"},
+ {0x03f1, "rhosymbolgreek"},
+ {0x02de, "rhotichookmod"},
+ {0x3271, "rieulacirclekorean"},
+ {0x3211, "rieulaparenkorean"},
+ {0x3263, "rieulcirclekorean"},
+ {0x3140, "rieulhieuhkorean"},
+ {0x313a, "rieulkiyeokkorean"},
+ {0x3169, "rieulkiyeoksioskorean"},
+ {0x3139, "rieulkorean"},
+ {0x313b, "rieulmieumkorean"},
+ {0x316c, "rieulpansioskorean"},
+ {0x3203, "rieulparenkorean"},
+ {0x313f, "rieulphieuphkorean"},
+ {0x313c, "rieulpieupkorean"},
+ {0x316b, "rieulpieupsioskorean"},
+ {0x313d, "rieulsioskorean"},
+ {0x313e, "rieulthieuthkorean"},
+ {0x316a, "rieultikeutkorean"},
+ {0x316d, "rieulyeorinhieuhkorean"},
+ {0x221f, "rightangle"},
+ {0x0319, "righttackbelowcmb"},
+ {0x22bf, "righttriangle"},
+ {0x308a, "rihiragana"},
+ {0x30ea, "rikatakana"},
+ {0xff98, "rikatakanahalfwidth"},
{0x02da, "ring"},
+ {0x0325, "ringbelowcmb"},
+ {0x030a, "ringcmb"},
+ {0x02bf, "ringhalfleft"},
+ {0x0559, "ringhalfleftarmenian"},
+ {0x031c, "ringhalfleftbelowcmb"},
+ {0x02d3, "ringhalfleftcentered"},
+ {0x02be, "ringhalfright"},
+ {0x0339, "ringhalfrightbelowcmb"},
+ {0x02d2, "ringhalfrightcentered"},
+ {0x0213, "rinvertedbreve"},
+ {0x3351, "rittorusquare"},
+ {0x1e5f, "rlinebelow"},
+ {0x027c, "rlongleg"},
+ {0x027a, "rlonglegturned"},
+ {0xff52, "rmonospace"},
+ {0x308d, "rohiragana"},
+ {0x30ed, "rokatakana"},
+ {0xff9b, "rokatakanahalfwidth"},
+ {0x0e23, "roruathai"},
+ {0x24ad, "rparen"},
+ {0x09dc, "rrabengali"},
+ {0x0931, "rradeva"},
+ {0x0a5c, "rragurmukhi"},
+ {0x0691, "rreharabic"},
+ {0xfb8d, "rrehfinalarabic"},
+ {0x09e0, "rrvocalicbengali"},
+ {0x0960, "rrvocalicdeva"},
+ {0x0ae0, "rrvocalicgujarati"},
+ {0x09c4, "rrvocalicvowelsignbengali"},
+ {0x0944, "rrvocalicvowelsigndeva"},
+ {0x0ac4, "rrvocalicvowelsigngujarati"},
{0xf6f1, "rsuperior"},
{0x2590, "rtblock"},
+ {0x0279, "rturned"},
+ {0x02b4, "rturnedsuperior"},
+ {0x308b, "ruhiragana"},
+ {0x30eb, "rukatakana"},
+ {0xff99, "rukatakanahalfwidth"},
+ {0x09f2, "rupeemarkbengali"},
+ {0x09f3, "rupeesignbengali"},
{0xf6dd, "rupiah"},
+ {0x0e24, "ruthai"},
+ {0x098b, "rvocalicbengali"},
+ {0x090b, "rvocalicdeva"},
+ {0x0a8b, "rvocalicgujarati"},
+ {0x09c3, "rvocalicvowelsignbengali"},
+ {0x0943, "rvocalicvowelsigndeva"},
+ {0x0ac3, "rvocalicvowelsigngujarati"},
{0x0073, "s"},
+ {0x09b8, "sabengali"},
{0x015b, "sacute"},
+ {0x1e65, "sacutedotaccent"},
+ {0x0635, "sadarabic"},
+ {0x0938, "sadeva"},
+ {0xfeba, "sadfinalarabic"},
+ {0xfebb, "sadinitialarabic"},
+ {0xfebc, "sadmedialarabic"},
+ {0x0ab8, "sagujarati"},
+ {0x0a38, "sagurmukhi"},
+ {0x3055, "sahiragana"},
+ {0x30b5, "sakatakana"},
+ {0xff7b, "sakatakanahalfwidth"},
+ {0xfdfa, "sallallahoualayhewasallamarabic"},
+ {0x05e1, "samekh"},
+ {0xfb41, "samekhdagesh"},
+ {0xfb41, "samekhdageshhebrew"},
+ {0x05e1, "samekhhebrew"},
+ {0x0e32, "saraaathai"},
+ {0x0e41, "saraaethai"},
+ {0x0e44, "saraaimaimalaithai"},
+ {0x0e43, "saraaimaimuanthai"},
+ {0x0e33, "saraamthai"},
+ {0x0e30, "saraathai"},
+ {0x0e40, "saraethai"},
+ {0xf886, "saraiileftthai"},
+ {0x0e35, "saraiithai"},
+ {0xf885, "saraileftthai"},
+ {0x0e34, "saraithai"},
+ {0x0e42, "saraothai"},
+ {0xf888, "saraueeleftthai"},
+ {0x0e37, "saraueethai"},
+ {0xf887, "saraueleftthai"},
+ {0x0e36, "sarauethai"},
+ {0x0e38, "sarauthai"},
+ {0x0e39, "sarauuthai"},
+ {0x3119, "sbopomofo"},
{0x0161, "scaron"},
+ {0x1e67, "scarondotaccent"},
{0x015f, "scedilla"},
+ {0x0259, "schwa"},
+ {0x04d9, "schwacyrillic"},
+ {0x04db, "schwadieresiscyrillic"},
+ {0x025a, "schwahook"},
+ {0x24e2, "scircle"},
{0x015d, "scircumflex"},
{0x0219, "scommaaccent"},
+ {0x1e61, "sdotaccent"},
+ {0x1e63, "sdotbelow"},
+ {0x1e69, "sdotbelowdotaccent"},
+ {0x033c, "seagullbelowcmb"},
{0x2033, "second"},
+ {0x02ca, "secondtonechinese"},
{0x00a7, "section"},
+ {0x0633, "seenarabic"},
+ {0xfeb2, "seenfinalarabic"},
+ {0xfeb3, "seeninitialarabic"},
+ {0xfeb4, "seenmedialarabic"},
+ {0x05b6, "segol"},
+ {0x05b6, "segol13"},
+ {0x05b6, "segol1f"},
+ {0x05b6, "segol2c"},
+ {0x05b6, "segolhebrew"},
+ {0x05b6, "segolnarrowhebrew"},
+ {0x05b6, "segolquarterhebrew"},
+ {0x0592, "segoltahebrew"},
+ {0x05b6, "segolwidehebrew"},
+ {0x057d, "seharmenian"},
+ {0x305b, "sehiragana"},
+ {0x30bb, "sekatakana"},
+ {0xff7e, "sekatakanahalfwidth"},
{0x003b, "semicolon"},
+ {0x061b, "semicolonarabic"},
+ {0xff1b, "semicolonmonospace"},
+ {0xfe54, "semicolonsmall"},
+ {0x309c, "semivoicedmarkkana"},
+ {0xff9f, "semivoicedmarkkanahalfwidth"},
+ {0x3322, "sentisquare"},
+ {0x3323, "sentosquare"},
{0x0037, "seven"},
+ {0x0667, "sevenarabic"},
+ {0x09ed, "sevenbengali"},
+ {0x2466, "sevencircle"},
+ {0x2790, "sevencircleinversesansserif"},
+ {0x096d, "sevendeva"},
{0x215e, "seveneighths"},
+ {0x0aed, "sevengujarati"},
+ {0x0a6d, "sevengurmukhi"},
+ {0x0667, "sevenhackarabic"},
+ {0x3027, "sevenhangzhou"},
+ {0x3226, "sevenideographicparen"},
{0x2087, "seveninferior"},
+ {0xff17, "sevenmonospace"},
{0xf737, "sevenoldstyle"},
+ {0x247a, "sevenparen"},
+ {0x248e, "sevenperiod"},
+ {0x06f7, "sevenpersian"},
+ {0x2176, "sevenroman"},
{0x2077, "sevensuperior"},
+ {0x2470, "seventeencircle"},
+ {0x2484, "seventeenparen"},
+ {0x2498, "seventeenperiod"},
+ {0x0e57, "seventhai"},
+ {0x00ad, "sfthyphen"},
+ {0x0577, "shaarmenian"},
+ {0x09b6, "shabengali"},
+ {0x0448, "shacyrillic"},
+ {0x0651, "shaddaarabic"},
+ {0xfc61, "shaddadammaarabic"},
+ {0xfc5e, "shaddadammatanarabic"},
+ {0xfc60, "shaddafathaarabic"},
+ {0xfc62, "shaddakasraarabic"},
+ {0xfc5f, "shaddakasratanarabic"},
{0x2592, "shade"},
+ {0x2593, "shadedark"},
+ {0x2591, "shadelight"},
+ {0x2592, "shademedium"},
+ {0x0936, "shadeva"},
+ {0x0ab6, "shagujarati"},
+ {0x0a36, "shagurmukhi"},
+ {0x0593, "shalshelethebrew"},
+ {0x3115, "shbopomofo"},
+ {0x0449, "shchacyrillic"},
+ {0x0634, "sheenarabic"},
+ {0xfeb6, "sheenfinalarabic"},
+ {0xfeb7, "sheeninitialarabic"},
+ {0xfeb8, "sheenmedialarabic"},
+ {0x03e3, "sheicoptic"},
+ {0x20aa, "sheqel"},
+ {0x20aa, "sheqelhebrew"},
+ {0x05b0, "sheva"},
+ {0x05b0, "sheva115"},
+ {0x05b0, "sheva15"},
+ {0x05b0, "sheva22"},
+ {0x05b0, "sheva2e"},
+ {0x05b0, "shevahebrew"},
+ {0x05b0, "shevanarrowhebrew"},
+ {0x05b0, "shevaquarterhebrew"},
+ {0x05b0, "shevawidehebrew"},
+ {0x04bb, "shhacyrillic"},
+ {0x03ed, "shimacoptic"},
+ {0x05e9, "shin"},
+ {0xfb49, "shindagesh"},
+ {0xfb49, "shindageshhebrew"},
+ {0xfb2c, "shindageshshindot"},
+ {0xfb2c, "shindageshshindothebrew"},
+ {0xfb2d, "shindageshsindot"},
+ {0xfb2d, "shindageshsindothebrew"},
+ {0x05c1, "shindothebrew"},
+ {0x05e9, "shinhebrew"},
+ {0xfb2a, "shinshindot"},
+ {0xfb2a, "shinshindothebrew"},
+ {0xfb2b, "shinsindot"},
+ {0xfb2b, "shinsindothebrew"},
+ {0x0282, "shook"},
{0x03c3, "sigma"},
{0x03c2, "sigma1"},
+ {0x03c2, "sigmafinal"},
+ {0x03f2, "sigmalunatesymbolgreek"},
+ {0x3057, "sihiragana"},
+ {0x30b7, "sikatakana"},
+ {0xff7c, "sikatakanahalfwidth"},
+ {0x05bd, "siluqhebrew"},
+ {0x05bd, "siluqlefthebrew"},
{0x223c, "similar"},
+ {0x05c2, "sindothebrew"},
+ {0x3274, "siosacirclekorean"},
+ {0x3214, "siosaparenkorean"},
+ {0x317e, "sioscieuckorean"},
+ {0x3266, "sioscirclekorean"},
+ {0x317a, "sioskiyeokkorean"},
+ {0x3145, "sioskorean"},
+ {0x317b, "siosnieunkorean"},
+ {0x3206, "siosparenkorean"},
+ {0x317d, "siospieupkorean"},
+ {0x317c, "siostikeutkorean"},
{0x0036, "six"},
+ {0x0666, "sixarabic"},
+ {0x09ec, "sixbengali"},
+ {0x2465, "sixcircle"},
+ {0x278f, "sixcircleinversesansserif"},
+ {0x096c, "sixdeva"},
+ {0x0aec, "sixgujarati"},
+ {0x0a6c, "sixgurmukhi"},
+ {0x0666, "sixhackarabic"},
+ {0x3026, "sixhangzhou"},
+ {0x3225, "sixideographicparen"},
{0x2086, "sixinferior"},
+ {0xff16, "sixmonospace"},
{0xf736, "sixoldstyle"},
+ {0x2479, "sixparen"},
+ {0x248d, "sixperiod"},
+ {0x06f6, "sixpersian"},
+ {0x2175, "sixroman"},
{0x2076, "sixsuperior"},
+ {0x246f, "sixteencircle"},
+ {0x09f9, "sixteencurrencydenominatorbengali"},
+ {0x2483, "sixteenparen"},
+ {0x2497, "sixteenperiod"},
+ {0x0e56, "sixthai"},
{0x002f, "slash"},
+ {0xff0f, "slashmonospace"},
+ {0x017f, "slong"},
+ {0x1e9b, "slongdotaccent"},
{0x263a, "smileface"},
+ {0xff53, "smonospace"},
+ {0x05c3, "sofpasuqhebrew"},
+ {0x00ad, "softhyphen"},
+ {0x044c, "softsigncyrillic"},
+ {0x305d, "sohiragana"},
+ {0x30bd, "sokatakana"},
+ {0xff7f, "sokatakanahalfwidth"},
+ {0x0338, "soliduslongoverlaycmb"},
+ {0x0337, "solidusshortoverlaycmb"},
+ {0x0e29, "sorusithai"},
+ {0x0e28, "sosalathai"},
+ {0x0e0b, "sosothai"},
+ {0x0e2a, "sosuathai"},
{0x0020, "space"},
+ {0x0020, "spacehackarabic"},
{0x2660, "spade"},
+ {0x2660, "spadesuitblack"},
+ {0x2664, "spadesuitwhite"},
+ {0x24ae, "sparen"},
+ {0x033b, "squarebelowcmb"},
+ {0x33c4, "squarecc"},
+ {0x339d, "squarecm"},
+ {0x25a9, "squarediagonalcrosshatchfill"},
+ {0x25a4, "squarehorizontalfill"},
+ {0x338f, "squarekg"},
+ {0x339e, "squarekm"},
+ {0x33ce, "squarekmcapital"},
+ {0x33d1, "squareln"},
+ {0x33d2, "squarelog"},
+ {0x338e, "squaremg"},
+ {0x33d5, "squaremil"},
+ {0x339c, "squaremm"},
+ {0x33a1, "squaremsquared"},
+ {0x25a6, "squareorthogonalcrosshatchfill"},
+ {0x25a7, "squareupperlefttolowerrightfill"},
+ {0x25a8, "squareupperrighttolowerleftfill"},
+ {0x25a5, "squareverticalfill"},
+ {0x25a3, "squarewhitewithsmallblack"},
+ {0x33db, "srsquare"},
+ {0x09b7, "ssabengali"},
+ {0x0937, "ssadeva"},
+ {0x0ab7, "ssagujarati"},
+ {0x3149, "ssangcieuckorean"},
+ {0x3185, "ssanghieuhkorean"},
+ {0x3180, "ssangieungkorean"},
+ {0x3132, "ssangkiyeokkorean"},
+ {0x3165, "ssangnieunkorean"},
+ {0x3143, "ssangpieupkorean"},
+ {0x3146, "ssangsioskorean"},
+ {0x3138, "ssangtikeutkorean"},
{0xf6f2, "ssuperior"},
{0x00a3, "sterling"},
+ {0xffe1, "sterlingmonospace"},
+ {0x0336, "strokelongoverlaycmb"},
+ {0x0335, "strokeshortoverlaycmb"},
+ {0x2282, "subset"},
+ {0x228a, "subsetnotequal"},
+ {0x2286, "subsetorequal"},
+ {0x227b, "succeeds"},
{0x220b, "suchthat"},
+ {0x3059, "suhiragana"},
+ {0x30b9, "sukatakana"},
+ {0xff7d, "sukatakanahalfwidth"},
+ {0x0652, "sukunarabic"},
{0x2211, "summation"},
{0x263c, "sun"},
+ {0x2283, "superset"},
+ {0x228b, "supersetnotequal"},
+ {0x2287, "supersetorequal"},
+ {0x33dc, "svsquare"},
+ {0x337c, "syouwaerasquare"},
{0x0074, "t"},
+ {0x09a4, "tabengali"},
+ {0x22a4, "tackdown"},
+ {0x22a3, "tackleft"},
+ {0x0924, "tadeva"},
+ {0x0aa4, "tagujarati"},
+ {0x0a24, "tagurmukhi"},
+ {0x0637, "taharabic"},
+ {0xfec2, "tahfinalarabic"},
+ {0xfec3, "tahinitialarabic"},
+ {0x305f, "tahiragana"},
+ {0xfec4, "tahmedialarabic"},
+ {0x337d, "taisyouerasquare"},
+ {0x30bf, "takatakana"},
+ {0xff80, "takatakanahalfwidth"},
+ {0x0640, "tatweelarabic"},
{0x03c4, "tau"},
+ {0x05ea, "tav"},
+ {0xfb4a, "tavdages"},
+ {0xfb4a, "tavdagesh"},
+ {0xfb4a, "tavdageshhebrew"},
+ {0x05ea, "tavhebrew"},
{0x0167, "tbar"},
+ {0x310a, "tbopomofo"},
{0x0165, "tcaron"},
+ {0x02a8, "tccurl"},
+ {0x0163, "tcedilla"},
+ {0x0686, "tcheharabic"},
+ {0xfb7b, "tchehfinalarabic"},
+ {0xfb7c, "tchehinitialarabic"},
+ {0xfb7d, "tchehmedialarabic"},
+ {0x24e3, "tcircle"},
+ {0x1e71, "tcircumflexbelow"},
{0x0163, "tcommaaccent"},
+ {0x1e97, "tdieresis"},
+ {0x1e6b, "tdotaccent"},
+ {0x1e6d, "tdotbelow"},
+ {0x0442, "tecyrillic"},
+ {0x04ad, "tedescendercyrillic"},
+ {0x062a, "teharabic"},
+ {0xfe96, "tehfinalarabic"},
+ {0xfca2, "tehhahinitialarabic"},
+ {0xfc0c, "tehhahisolatedarabic"},
+ {0xfe97, "tehinitialarabic"},
+ {0x3066, "tehiragana"},
+ {0xfca1, "tehjeeminitialarabic"},
+ {0xfc0b, "tehjeemisolatedarabic"},
+ {0x0629, "tehmarbutaarabic"},
+ {0xfe94, "tehmarbutafinalarabic"},
+ {0xfe98, "tehmedialarabic"},
+ {0xfca4, "tehmeeminitialarabic"},
+ {0xfc0e, "tehmeemisolatedarabic"},
+ {0xfc73, "tehnoonfinalarabic"},
+ {0x30c6, "tekatakana"},
+ {0xff83, "tekatakanahalfwidth"},
+ {0x2121, "telephone"},
+ {0x260e, "telephoneblack"},
+ {0x05a0, "telishagedolahebrew"},
+ {0x05a9, "telishaqetanahebrew"},
+ {0x2469, "tencircle"},
+ {0x3229, "tenideographicparen"},
+ {0x247d, "tenparen"},
+ {0x2491, "tenperiod"},
+ {0x2179, "tenroman"},
+ {0x02a7, "tesh"},
+ {0x05d8, "tet"},
+ {0xfb38, "tetdagesh"},
+ {0xfb38, "tetdageshhebrew"},
+ {0x05d8, "tethebrew"},
+ {0x04b5, "tetsecyrillic"},
+ {0x059b, "tevirhebrew"},
+ {0x059b, "tevirlefthebrew"},
+ {0x09a5, "thabengali"},
+ {0x0925, "thadeva"},
+ {0x0aa5, "thagujarati"},
+ {0x0a25, "thagurmukhi"},
+ {0x0630, "thalarabic"},
+ {0xfeac, "thalfinalarabic"},
+ {0xf898, "thanthakhatlowleftthai"},
+ {0xf897, "thanthakhatlowrightthai"},
+ {0x0e4c, "thanthakhatthai"},
+ {0xf896, "thanthakhatupperleftthai"},
+ {0x062b, "theharabic"},
+ {0xfe9a, "thehfinalarabic"},
+ {0xfe9b, "thehinitialarabic"},
+ {0xfe9c, "thehmedialarabic"},
+ {0x2203, "thereexists"},
{0x2234, "therefore"},
{0x03b8, "theta"},
{0x03d1, "theta1"},
+ {0x03d1, "thetasymbolgreek"},
+ {0x3279, "thieuthacirclekorean"},
+ {0x3219, "thieuthaparenkorean"},
+ {0x326b, "thieuthcirclekorean"},
+ {0x314c, "thieuthkorean"},
+ {0x320b, "thieuthparenkorean"},
+ {0x246c, "thirteencircle"},
+ {0x2480, "thirteenparen"},
+ {0x2494, "thirteenperiod"},
+ {0x0e11, "thonangmonthothai"},
+ {0x01ad, "thook"},
+ {0x0e12, "thophuthaothai"},
{0x00fe, "thorn"},
+ {0x0e17, "thothahanthai"},
+ {0x0e10, "thothanthai"},
+ {0x0e18, "thothongthai"},
+ {0x0e16, "thothungthai"},
+ {0x0482, "thousandcyrillic"},
+ {0x066c, "thousandsseparatorarabic"},
+ {0x066c, "thousandsseparatorpersian"},
{0x0033, "three"},
+ {0x0663, "threearabic"},
+ {0x09e9, "threebengali"},
+ {0x2462, "threecircle"},
+ {0x278c, "threecircleinversesansserif"},
+ {0x0969, "threedeva"},
{0x215c, "threeeighths"},
+ {0x0ae9, "threegujarati"},
+ {0x0a69, "threegurmukhi"},
+ {0x0663, "threehackarabic"},
+ {0x3023, "threehangzhou"},
+ {0x3222, "threeideographicparen"},
{0x2083, "threeinferior"},
+ {0xff13, "threemonospace"},
+ {0x09f6, "threenumeratorbengali"},
{0xf733, "threeoldstyle"},
+ {0x2476, "threeparen"},
+ {0x248a, "threeperiod"},
+ {0x06f3, "threepersian"},
{0x00be, "threequarters"},
{0xf6de, "threequartersemdash"},
+ {0x2172, "threeroman"},
{0x00b3, "threesuperior"},
+ {0x0e53, "threethai"},
+ {0x3394, "thzsquare"},
+ {0x3061, "tihiragana"},
+ {0x30c1, "tikatakana"},
+ {0xff81, "tikatakanahalfwidth"},
+ {0x3270, "tikeutacirclekorean"},
+ {0x3210, "tikeutaparenkorean"},
+ {0x3262, "tikeutcirclekorean"},
+ {0x3137, "tikeutkorean"},
+ {0x3202, "tikeutparenkorean"},
{0x02dc, "tilde"},
+ {0x0330, "tildebelowcmb"},
+ {0x0303, "tildecmb"},
{0x0303, "tildecomb"},
+ {0x0360, "tildedoublecmb"},
+ {0x223c, "tildeoperator"},
+ {0x0334, "tildeoverlaycmb"},
+ {0x033e, "tildeverticalcmb"},
+ {0x2297, "timescircle"},
+ {0x0596, "tipehahebrew"},
+ {0x0596, "tipehalefthebrew"},
+ {0x0a70, "tippigurmukhi"},
+ {0x0483, "titlocyrilliccmb"},
+ {0x057f, "tiwnarmenian"},
+ {0x1e6f, "tlinebelow"},
+ {0xff54, "tmonospace"},
+ {0x0569, "toarmenian"},
+ {0x3068, "tohiragana"},
+ {0x30c8, "tokatakana"},
+ {0xff84, "tokatakanahalfwidth"},
+ {0x02e5, "tonebarextrahighmod"},
+ {0x02e9, "tonebarextralowmod"},
+ {0x02e6, "tonebarhighmod"},
+ {0x02e8, "tonebarlowmod"},
+ {0x02e7, "tonebarmidmod"},
+ {0x01bd, "tonefive"},
+ {0x0185, "tonesix"},
+ {0x01a8, "tonetwo"},
{0x0384, "tonos"},
+ {0x3327, "tonsquare"},
+ {0x0e0f, "topatakthai"},
+ {0x3014, "tortoiseshellbracketleft"},
+ {0xfe5d, "tortoiseshellbracketleftsmall"},
+ {0xfe39, "tortoiseshellbracketleftvertical"},
+ {0x3015, "tortoiseshellbracketright"},
+ {0xfe5e, "tortoiseshellbracketrightsmall"},
+ {0xfe3a, "tortoiseshellbracketrightvertical"},
+ {0x0e15, "totaothai"},
+ {0x01ab, "tpalatalhook"},
+ {0x24af, "tparen"},
{0x2122, "trademark"},
{0x2122, "trademarksans"},
{0x2122, "trademarkserif"},
+ {0x0288, "tretroflexhook"},
{0x25bc, "triagdn"},
{0x25c4, "triaglf"},
{0x25ba, "triagrt"},
{0x25b2, "triagup"},
+ {0x02a6, "ts"},
+ {0x05e6, "tsadi"},
+ {0xfb46, "tsadidagesh"},
+ {0xfb46, "tsadidageshhebrew"},
+ {0x05e6, "tsadihebrew"},
+ {0x0446, "tsecyrillic"},
+ {0x05b5, "tsere"},
+ {0x05b5, "tsere12"},
+ {0x05b5, "tsere1e"},
+ {0x05b5, "tsere2b"},
+ {0x05b5, "tserehebrew"},
+ {0x05b5, "tserenarrowhebrew"},
+ {0x05b5, "tserequarterhebrew"},
+ {0x05b5, "tserewidehebrew"},
+ {0x045b, "tshecyrillic"},
{0xf6f3, "tsuperior"},
+ {0x099f, "ttabengali"},
+ {0x091f, "ttadeva"},
+ {0x0a9f, "ttagujarati"},
+ {0x0a1f, "ttagurmukhi"},
+ {0x0679, "tteharabic"},
+ {0xfb67, "ttehfinalarabic"},
+ {0xfb68, "ttehinitialarabic"},
+ {0xfb69, "ttehmedialarabic"},
+ {0x09a0, "tthabengali"},
+ {0x0920, "tthadeva"},
+ {0x0aa0, "tthagujarati"},
+ {0x0a20, "tthagurmukhi"},
+ {0x0287, "tturned"},
+ {0x3064, "tuhiragana"},
+ {0x30c4, "tukatakana"},
+ {0xff82, "tukatakanahalfwidth"},
+ {0x3063, "tusmallhiragana"},
+ {0x30c3, "tusmallkatakana"},
+ {0xff6f, "tusmallkatakanahalfwidth"},
+ {0x246b, "twelvecircle"},
+ {0x247f, "twelveparen"},
+ {0x2493, "twelveperiod"},
+ {0x217b, "twelveroman"},
+ {0x2473, "twentycircle"},
+ {0x5344, "twentyhangzhou"},
+ {0x2487, "twentyparen"},
+ {0x249b, "twentyperiod"},
{0x0032, "two"},
+ {0x0662, "twoarabic"},
+ {0x09e8, "twobengali"},
+ {0x2461, "twocircle"},
+ {0x278b, "twocircleinversesansserif"},
+ {0x0968, "twodeva"},
{0x2025, "twodotenleader"},
+ {0x2025, "twodotleader"},
+ {0xfe30, "twodotleadervertical"},
+ {0x0ae8, "twogujarati"},
+ {0x0a68, "twogurmukhi"},
+ {0x0662, "twohackarabic"},
+ {0x3022, "twohangzhou"},
+ {0x3221, "twoideographicparen"},
{0x2082, "twoinferior"},
+ {0xff12, "twomonospace"},
+ {0x09f5, "twonumeratorbengali"},
{0xf732, "twooldstyle"},
+ {0x2475, "twoparen"},
+ {0x2489, "twoperiod"},
+ {0x06f2, "twopersian"},
+ {0x2171, "tworoman"},
+ {0x01bb, "twostroke"},
{0x00b2, "twosuperior"},
+ {0x0e52, "twothai"},
{0x2154, "twothirds"},
{0x0075, "u"},
{0x00fa, "uacute"},
+ {0x0289, "ubar"},
+ {0x0989, "ubengali"},
+ {0x3128, "ubopomofo"},
{0x016d, "ubreve"},
+ {0x01d4, "ucaron"},
+ {0x24e4, "ucircle"},
{0x00fb, "ucircumflex"},
+ {0x1e77, "ucircumflexbelow"},
+ {0x0443, "ucyrillic"},
+ {0x0951, "udattadeva"},
+ {0x0171, "udblacute"},
+ {0x0215, "udblgrave"},
+ {0x0909, "udeva"},
{0x00fc, "udieresis"},
+ {0x01d8, "udieresisacute"},
+ {0x1e73, "udieresisbelow"},
+ {0x01da, "udieresiscaron"},
+ {0x04f1, "udieresiscyrillic"},
+ {0x01dc, "udieresisgrave"},
+ {0x01d6, "udieresismacron"},
+ {0x1ee5, "udotbelow"},
{0x00f9, "ugrave"},
+ {0x0a89, "ugujarati"},
+ {0x0a09, "ugurmukhi"},
+ {0x3046, "uhiragana"},
+ {0x1ee7, "uhookabove"},
{0x01b0, "uhorn"},
+ {0x1ee9, "uhornacute"},
+ {0x1ef1, "uhorndotbelow"},
+ {0x1eeb, "uhorngrave"},
+ {0x1eed, "uhornhookabove"},
+ {0x1eef, "uhorntilde"},
{0x0171, "uhungarumlaut"},
+ {0x04f3, "uhungarumlautcyrillic"},
+ {0x0217, "uinvertedbreve"},
+ {0x30a6, "ukatakana"},
+ {0xff73, "ukatakanahalfwidth"},
+ {0x0479, "ukcyrillic"},
+ {0x315c, "ukorean"},
{0x016b, "umacron"},
+ {0x04ef, "umacroncyrillic"},
+ {0x1e7b, "umacrondieresis"},
+ {0x0a41, "umatragurmukhi"},
+ {0xff55, "umonospace"},
{0x005f, "underscore"},
{0x2017, "underscoredbl"},
+ {0xff3f, "underscoremonospace"},
+ {0xfe33, "underscorevertical"},
+ {0xfe4f, "underscorewavy"},
{0x222a, "union"},
{0x2200, "universal"},
{0x0173, "uogonek"},
+ {0x24b0, "uparen"},
{0x2580, "upblock"},
+ {0x05c4, "upperdothebrew"},
{0x03c5, "upsilon"},
{0x03cb, "upsilondieresis"},
{0x03b0, "upsilondieresistonos"},
+ {0x028a, "upsilonlatin"},
{0x03cd, "upsilontonos"},
+ {0x031d, "uptackbelowcmb"},
+ {0x02d4, "uptackmod"},
+ {0x0a73, "uragurmukhi"},
{0x016f, "uring"},
+ {0x045e, "ushortcyrillic"},
+ {0x3045, "usmallhiragana"},
+ {0x30a5, "usmallkatakana"},
+ {0xff69, "usmallkatakanahalfwidth"},
+ {0x04af, "ustraightcyrillic"},
+ {0x04b1, "ustraightstrokecyrillic"},
{0x0169, "utilde"},
+ {0x1e79, "utildeacute"},
+ {0x1e75, "utildebelow"},
+ {0x098a, "uubengali"},
+ {0x090a, "uudeva"},
+ {0x0a8a, "uugujarati"},
+ {0x0a0a, "uugurmukhi"},
+ {0x0a42, "uumatragurmukhi"},
+ {0x09c2, "uuvowelsignbengali"},
+ {0x0942, "uuvowelsigndeva"},
+ {0x0ac2, "uuvowelsigngujarati"},
+ {0x09c1, "uvowelsignbengali"},
+ {0x0941, "uvowelsigndeva"},
+ {0x0ac1, "uvowelsigngujarati"},
{0x0076, "v"},
+ {0x0935, "vadeva"},
+ {0x0ab5, "vagujarati"},
+ {0x0a35, "vagurmukhi"},
+ {0x30f7, "vakatakana"},
+ {0x05d5, "vav"},
+ {0xfb35, "vavdagesh"},
+ {0xfb35, "vavdagesh65"},
+ {0xfb35, "vavdageshhebrew"},
+ {0x05d5, "vavhebrew"},
+ {0xfb4b, "vavholam"},
+ {0xfb4b, "vavholamhebrew"},
+ {0x05f0, "vavvavhebrew"},
+ {0x05f1, "vavyodhebrew"},
+ {0x24e5, "vcircle"},
+ {0x1e7f, "vdotbelow"},
+ {0x0432, "vecyrillic"},
+ {0x06a4, "veharabic"},
+ {0xfb6b, "vehfinalarabic"},
+ {0xfb6c, "vehinitialarabic"},
+ {0xfb6d, "vehmedialarabic"},
+ {0x30f9, "vekatakana"},
+ {0x2640, "venus"},
+ {0x007c, "verticalbar"},
+ {0x030d, "verticallineabovecmb"},
+ {0x0329, "verticallinebelowcmb"},
+ {0x02cc, "verticallinelowmod"},
+ {0x02c8, "verticallinemod"},
+ {0x057e, "vewarmenian"},
+ {0x028b, "vhook"},
+ {0x30f8, "vikatakana"},
+ {0x09cd, "viramabengali"},
+ {0x094d, "viramadeva"},
+ {0x0acd, "viramagujarati"},
+ {0x0983, "visargabengali"},
+ {0x0903, "visargadeva"},
+ {0x0a83, "visargagujarati"},
+ {0xff56, "vmonospace"},
+ {0x0578, "voarmenian"},
+ {0x309e, "voicediterationhiragana"},
+ {0x30fe, "voicediterationkatakana"},
+ {0x309b, "voicedmarkkana"},
+ {0xff9e, "voicedmarkkanahalfwidth"},
+ {0x30fa, "vokatakana"},
+ {0x24b1, "vparen"},
+ {0x1e7d, "vtilde"},
+ {0x028c, "vturned"},
+ {0x3094, "vuhiragana"},
+ {0x30f4, "vukatakana"},
{0x0077, "w"},
{0x1e83, "wacute"},
+ {0x3159, "waekorean"},
+ {0x308f, "wahiragana"},
+ {0x30ef, "wakatakana"},
+ {0xff9c, "wakatakanahalfwidth"},
+ {0x3158, "wakorean"},
+ {0x308e, "wasmallhiragana"},
+ {0x30ee, "wasmallkatakana"},
+ {0x3357, "wattosquare"},
+ {0x301c, "wavedash"},
+ {0xfe34, "wavyunderscorevertical"},
+ {0x0648, "wawarabic"},
+ {0xfeee, "wawfinalarabic"},
+ {0x0624, "wawhamzaabovearabic"},
+ {0xfe86, "wawhamzaabovefinalarabic"},
+ {0x33dd, "wbsquare"},
+ {0x24e6, "wcircle"},
{0x0175, "wcircumflex"},
{0x1e85, "wdieresis"},
+ {0x1e87, "wdotaccent"},
+ {0x1e89, "wdotbelow"},
+ {0x3091, "wehiragana"},
{0x2118, "weierstrass"},
+ {0x30f1, "wekatakana"},
+ {0x315e, "wekorean"},
+ {0x315d, "weokorean"},
{0x1e81, "wgrave"},
+ {0x25e6, "whitebullet"},
+ {0x25cb, "whitecircle"},
+ {0x25d9, "whitecircleinverse"},
+ {0x300e, "whitecornerbracketleft"},
+ {0xfe43, "whitecornerbracketleftvertical"},
+ {0x300f, "whitecornerbracketright"},
+ {0xfe44, "whitecornerbracketrightvertical"},
+ {0x25c7, "whitediamond"},
+ {0x25c8, "whitediamondcontainingblacksmalldiamond"},
+ {0x25bf, "whitedownpointingsmalltriangle"},
+ {0x25bd, "whitedownpointingtriangle"},
+ {0x25c3, "whiteleftpointingsmalltriangle"},
+ {0x25c1, "whiteleftpointingtriangle"},
+ {0x3016, "whitelenticularbracketleft"},
+ {0x3017, "whitelenticularbracketright"},
+ {0x25b9, "whiterightpointingsmalltriangle"},
+ {0x25b7, "whiterightpointingtriangle"},
+ {0x25ab, "whitesmallsquare"},
+ {0x263a, "whitesmilingface"},
+ {0x25a1, "whitesquare"},
+ {0x2606, "whitestar"},
+ {0x260f, "whitetelephone"},
+ {0x3018, "whitetortoiseshellbracketleft"},
+ {0x3019, "whitetortoiseshellbracketright"},
+ {0x25b5, "whiteuppointingsmalltriangle"},
+ {0x25b3, "whiteuppointingtriangle"},
+ {0x3090, "wihiragana"},
+ {0x30f0, "wikatakana"},
+ {0x315f, "wikorean"},
+ {0xff57, "wmonospace"},
+ {0x3092, "wohiragana"},
+ {0x30f2, "wokatakana"},
+ {0xff66, "wokatakanahalfwidth"},
+ {0x20a9, "won"},
+ {0xffe6, "wonmonospace"},
+ {0x0e27, "wowaenthai"},
+ {0x24b2, "wparen"},
+ {0x1e98, "wring"},
+ {0x02b7, "wsuperior"},
+ {0x028d, "wturned"},
+ {0x01bf, "wynn"},
{0x0078, "x"},
+ {0x033d, "xabovecmb"},
+ {0x3112, "xbopomofo"},
+ {0x24e7, "xcircle"},
+ {0x1e8d, "xdieresis"},
+ {0x1e8b, "xdotaccent"},
+ {0x056d, "xeharmenian"},
{0x03be, "xi"},
+ {0xff58, "xmonospace"},
+ {0x24b3, "xparen"},
+ {0x02e3, "xsuperior"},
{0x0079, "y"},
+ {0x334e, "yaadosquare"},
+ {0x09af, "yabengali"},
{0x00fd, "yacute"},
+ {0x092f, "yadeva"},
+ {0x3152, "yaekorean"},
+ {0x0aaf, "yagujarati"},
+ {0x0a2f, "yagurmukhi"},
+ {0x3084, "yahiragana"},
+ {0x30e4, "yakatakana"},
+ {0xff94, "yakatakanahalfwidth"},
+ {0x3151, "yakorean"},
+ {0x0e4e, "yamakkanthai"},
+ {0x3083, "yasmallhiragana"},
+ {0x30e3, "yasmallkatakana"},
+ {0xff6c, "yasmallkatakanahalfwidth"},
+ {0x0463, "yatcyrillic"},
+ {0x24e8, "ycircle"},
{0x0177, "ycircumflex"},
{0x00ff, "ydieresis"},
+ {0x1e8f, "ydotaccent"},
+ {0x1ef5, "ydotbelow"},
+ {0x064a, "yeharabic"},
+ {0x06d2, "yehbarreearabic"},
+ {0xfbaf, "yehbarreefinalarabic"},
+ {0xfef2, "yehfinalarabic"},
+ {0x0626, "yehhamzaabovearabic"},
+ {0xfe8a, "yehhamzaabovefinalarabic"},
+ {0xfe8b, "yehhamzaaboveinitialarabic"},
+ {0xfe8c, "yehhamzaabovemedialarabic"},
+ {0xfef3, "yehinitialarabic"},
+ {0xfef4, "yehmedialarabic"},
+ {0xfcdd, "yehmeeminitialarabic"},
+ {0xfc58, "yehmeemisolatedarabic"},
+ {0xfc94, "yehnoonfinalarabic"},
+ {0x06d1, "yehthreedotsbelowarabic"},
+ {0x3156, "yekorean"},
{0x00a5, "yen"},
+ {0xffe5, "yenmonospace"},
+ {0x3155, "yeokorean"},
+ {0x3186, "yeorinhieuhkorean"},
+ {0x05aa, "yerahbenyomohebrew"},
+ {0x05aa, "yerahbenyomolefthebrew"},
+ {0x044b, "yericyrillic"},
+ {0x04f9, "yerudieresiscyrillic"},
+ {0x3181, "yesieungkorean"},
+ {0x3183, "yesieungpansioskorean"},
+ {0x3182, "yesieungsioskorean"},
+ {0x059a, "yetivhebrew"},
{0x1ef3, "ygrave"},
+ {0x01b4, "yhook"},
+ {0x1ef7, "yhookabove"},
+ {0x0575, "yiarmenian"},
+ {0x0457, "yicyrillic"},
+ {0x3162, "yikorean"},
+ {0x262f, "yinyang"},
+ {0x0582, "yiwnarmenian"},
+ {0xff59, "ymonospace"},
+ {0x05d9, "yod"},
+ {0xfb39, "yoddagesh"},
+ {0xfb39, "yoddageshhebrew"},
+ {0x05d9, "yodhebrew"},
+ {0x05f2, "yodyodhebrew"},
+ {0xfb1f, "yodyodpatahhebrew"},
+ {0x3088, "yohiragana"},
+ {0x3189, "yoikorean"},
+ {0x30e8, "yokatakana"},
+ {0xff96, "yokatakanahalfwidth"},
+ {0x315b, "yokorean"},
+ {0x3087, "yosmallhiragana"},
+ {0x30e7, "yosmallkatakana"},
+ {0xff6e, "yosmallkatakanahalfwidth"},
+ {0x03f3, "yotgreek"},
+ {0x3188, "yoyaekorean"},
+ {0x3187, "yoyakorean"},
+ {0x0e22, "yoyakthai"},
+ {0x0e0d, "yoyingthai"},
+ {0x24b4, "yparen"},
+ {0x037a, "ypogegrammeni"},
+ {0x0345, "ypogegrammenigreekcmb"},
+ {0x01a6, "yr"},
+ {0x1e99, "yring"},
+ {0x02b8, "ysuperior"},
+ {0x1ef9, "ytilde"},
+ {0x028e, "yturned"},
+ {0x3086, "yuhiragana"},
+ {0x318c, "yuikorean"},
+ {0x30e6, "yukatakana"},
+ {0xff95, "yukatakanahalfwidth"},
+ {0x3160, "yukorean"},
+ {0x046b, "yusbigcyrillic"},
+ {0x046d, "yusbigiotifiedcyrillic"},
+ {0x0467, "yuslittlecyrillic"},
+ {0x0469, "yuslittleiotifiedcyrillic"},
+ {0x3085, "yusmallhiragana"},
+ {0x30e5, "yusmallkatakana"},
+ {0xff6d, "yusmallkatakanahalfwidth"},
+ {0x318b, "yuyekorean"},
+ {0x318a, "yuyeokorean"},
+ {0x09df, "yyabengali"},
+ {0x095f, "yyadeva"},
{0x007a, "z"},
+ {0x0566, "zaarmenian"},
{0x017a, "zacute"},
+ {0x095b, "zadeva"},
+ {0x0a5b, "zagurmukhi"},
+ {0x0638, "zaharabic"},
+ {0xfec6, "zahfinalarabic"},
+ {0xfec7, "zahinitialarabic"},
+ {0x3056, "zahiragana"},
+ {0xfec8, "zahmedialarabic"},
+ {0x0632, "zainarabic"},
+ {0xfeb0, "zainfinalarabic"},
+ {0x30b6, "zakatakana"},
+ {0x0595, "zaqefgadolhebrew"},
+ {0x0594, "zaqefqatanhebrew"},
+ {0x0598, "zarqahebrew"},
+ {0x05d6, "zayin"},
+ {0xfb36, "zayindagesh"},
+ {0xfb36, "zayindageshhebrew"},
+ {0x05d6, "zayinhebrew"},
+ {0x3117, "zbopomofo"},
{0x017e, "zcaron"},
+ {0x24e9, "zcircle"},
+ {0x1e91, "zcircumflex"},
+ {0x0291, "zcurl"},
+ {0x017c, "zdot"},
{0x017c, "zdotaccent"},
+ {0x1e93, "zdotbelow"},
+ {0x0437, "zecyrillic"},
+ {0x0499, "zedescendercyrillic"},
+ {0x04df, "zedieresiscyrillic"},
+ {0x305c, "zehiragana"},
+ {0x30bc, "zekatakana"},
{0x0030, "zero"},
+ {0x0660, "zeroarabic"},
+ {0x09e6, "zerobengali"},
+ {0x0966, "zerodeva"},
+ {0x0ae6, "zerogujarati"},
+ {0x0a66, "zerogurmukhi"},
+ {0x0660, "zerohackarabic"},
{0x2080, "zeroinferior"},
+ {0xff10, "zeromonospace"},
{0xf730, "zerooldstyle"},
+ {0x06f0, "zeropersian"},
{0x2070, "zerosuperior"},
+ {0x0e50, "zerothai"},
+ {0xfeff, "zerowidthjoiner"},
+ {0x200c, "zerowidthnonjoiner"},
+ {0x200b, "zerowidthspace"},
{0x03b6, "zeta"},
+ {0x3113, "zhbopomofo"},
+ {0x056a, "zhearmenian"},
+ {0x04c2, "zhebrevecyrillic"},
+ {0x0436, "zhecyrillic"},
+ {0x0497, "zhedescendercyrillic"},
+ {0x04dd, "zhedieresiscyrillic"},
+ {0x3058, "zihiragana"},
+ {0x30b8, "zikatakana"},
+ {0x05ae, "zinorhebrew"},
+ {0x1e95, "zlinebelow"},
+ {0xff5a, "zmonospace"},
+ {0x305e, "zohiragana"},
+ {0x30be, "zokatakana"},
+ {0x24b5, "zparen"},
+ {0x0290, "zretroflexhook"},
+ {0x01b6, "zstroke"},
+ {0x305a, "zuhiragana"},
+ {0x30ba, "zukatakana"},
{0x007b, "{"},
{0x007c, "|"},
{0x007d, "}"},
diff --git a/xpdf/Object.cc b/xpdf/Object.cc
index 71c632a..3536bcf 100644
--- a/xpdf/Object.cc
+++ b/xpdf/Object.cc
@@ -24,7 +24,7 @@
// Object
//------------------------------------------------------------------------
-char *objTypeNames[numObjTypes] = {
+const char *objTypeNames[numObjTypes] = {
"boolean",
"integer",
"real",
@@ -101,9 +101,9 @@ Object *Object::copy(Object *obj) {
return obj;
}
-Object *Object::fetch(XRef *xref, Object *obj) {
+Object *Object::fetch(XRef *xref, Object *obj, int recursion) {
return (type == objRef && xref) ?
- xref->fetch(ref.num, ref.gen, obj) : copy(obj);
+ xref->fetch(ref.num, ref.gen, obj, recursion) : copy(obj);
}
void Object::free() {
@@ -141,7 +141,7 @@ void Object::free() {
type = objNone;
}
-char *Object::getTypeName() {
+const char *Object::getTypeName() {
return objTypeNames[type];
}
diff --git a/xpdf/Object.h b/xpdf/Object.h
index 8b1807c..e1abed9 100644
--- a/xpdf/Object.h
+++ b/xpdf/Object.h
@@ -89,7 +89,7 @@ public:
{ initObj(objReal); real = realA; return this; }
Object *initString(GString *stringA)
{ initObj(objString); string = stringA; return this; }
- Object *initName(char *nameA)
+ Object *initName(const char *nameA)
{ initObj(objName); name = copyString(nameA); return this; }
Object *initNull()
{ initObj(objNull); return this; }
@@ -111,7 +111,7 @@ public:
// If object is a Ref, fetch and return the referenced object.
// Otherwise, return a copy of the object.
- Object *fetch(XRef *xref, Object *obj);
+ Object *fetch(XRef *xref, Object *obj, int recursion = 0);
// Free object contents.
void free();
@@ -135,11 +135,11 @@ public:
GBool isNone() { return type == objNone; }
// Special type checking.
- GBool isName(char *nameA)
+ GBool isName(const char *nameA)
{ return type == objName && !strcmp(name, nameA); }
- GBool isDict(char *dictType);
+ GBool isDict(const char *dictType);
GBool isStream(char *dictType);
- GBool isCmd(char *cmdA)
+ GBool isCmd(const char *cmdA)
{ return type == objCmd && !strcmp(cmd, cmdA); }
// Accessors. NB: these assume object is of correct type.
@@ -166,9 +166,9 @@ public:
// Dict accessors.
int dictGetLength();
void dictAdd(char *key, Object *val);
- GBool dictIs(char *dictType);
- Object *dictLookup(char *key, Object *obj);
- Object *dictLookupNF(char *key, Object *obj);
+ GBool dictIs(const char *dictType);
+ Object *dictLookup(const char *key, Object *obj, int recursion = 0);
+ Object *dictLookupNF(const char *key, Object *obj);
char *dictGetKey(int i);
Object *dictGetVal(int i, Object *obj);
Object *dictGetValNF(int i, Object *obj);
@@ -185,7 +185,7 @@ public:
Dict *streamGetDict();
// Output.
- char *getTypeName();
+ const char *getTypeName();
void print(FILE *f = stdout);
// Memory testing.
@@ -243,16 +243,16 @@ inline int Object::dictGetLength()
inline void Object::dictAdd(char *key, Object *val)
{ dict->add(key, val); }
-inline GBool Object::dictIs(char *dictType)
+inline GBool Object::dictIs(const char *dictType)
{ return dict->is(dictType); }
-inline GBool Object::isDict(char *dictType)
+inline GBool Object::isDict(const char *dictType)
{ return type == objDict && dictIs(dictType); }
-inline Object *Object::dictLookup(char *key, Object *obj)
- { return dict->lookup(key, obj); }
+inline Object *Object::dictLookup(const char *key, Object *obj, int recursion)
+ { return dict->lookup(key, obj, recursion); }
-inline Object *Object::dictLookupNF(char *key, Object *obj)
+inline Object *Object::dictLookupNF(const char *key, Object *obj)
{ return dict->lookupNF(key, obj); }
inline char *Object::dictGetKey(int i)
diff --git a/xpdf/OptionalContent.cc b/xpdf/OptionalContent.cc
new file mode 100644
index 0000000..589719c
--- /dev/null
+++ b/xpdf/OptionalContent.cc
@@ -0,0 +1,500 @@
+//========================================================================
+//
+// OptionalContent.cc
+//
+// Copyright 2008 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "GString.h"
+#include "GList.h"
+#include "Error.h"
+#include "Object.h"
+#include "PDFDoc.h"
+#include "PDFDocEncoding.h"
+#include "OptionalContent.h"
+
+//------------------------------------------------------------------------
+
+#define ocPolicyAllOn 1
+#define ocPolicyAnyOn 2
+#define ocPolicyAnyOff 3
+#define ocPolicyAllOff 4
+
+//------------------------------------------------------------------------
+
+// Max depth of nested visibility expressions. This is used to catch
+// infinite loops in the visibility expression object structure.
+#define visibilityExprRecursionLimit 50
+
+// Max depth of nested display nodes. This is used to catch infinite
+// loops in the "Order" object structure.
+#define displayNodeRecursionLimit 50
+
+//------------------------------------------------------------------------
+
+OptionalContent::OptionalContent(PDFDoc *doc) {
+ Object *ocProps;
+ Object ocgList, defView, obj1, obj2;
+ Ref ref1;
+ OptionalContentGroup *ocg;
+ int i;
+
+ xref = doc->getXRef();
+ ocgs = new GList();
+ display = NULL;
+
+ if ((ocProps = doc->getCatalog()->getOCProperties())->isDict()) {
+ if (ocProps->dictLookup("OCGs", &ocgList)->isArray()) {
+
+ //----- read the OCG list
+ for (i = 0; i < ocgList.arrayGetLength(); ++i) {
+ if (ocgList.arrayGetNF(i, &obj1)->isRef()) {
+ ref1 = obj1.getRef();
+ obj1.fetch(xref, &obj2);
+ if ((ocg = OptionalContentGroup::parse(&ref1, &obj2))) {
+ ocgs->append(ocg);
+ }
+ obj2.free();
+ }
+ obj1.free();
+ }
+
+ //----- read the default viewing OCCD
+ if (ocProps->dictLookup("D", &defView)->isDict()) {
+
+ //----- initial state
+ if (defView.dictLookup("OFF", &obj1)->isArray()) {
+ for (i = 0; i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGetNF(i, &obj2)->isRef()) {
+ ref1 = obj2.getRef();
+ if ((ocg = findOCG(&ref1))) {
+ ocg->setState(gFalse);
+ } else {
+ error(errSyntaxError, -1,
+ "Invalid OCG reference in OFF array in default viewing OCCD");
+ }
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ //----- display order
+ if (defView.dictLookup("Order", &obj1)->isArray()) {
+ display = OCDisplayNode::parse(&obj1, this, xref);
+ }
+ obj1.free();
+
+ } else {
+ error(errSyntaxError, -1, "Missing or invalid default viewing OCCD");
+ }
+ defView.free();
+
+ }
+ ocgList.free();
+ }
+
+ if (!display) {
+ display = new OCDisplayNode();
+ }
+}
+
+OptionalContent::~OptionalContent() {
+ deleteGList(ocgs, OptionalContentGroup);
+ delete display;
+}
+
+int OptionalContent::getNumOCGs() {
+ return ocgs->getLength();
+}
+
+OptionalContentGroup *OptionalContent::getOCG(int idx) {
+ return (OptionalContentGroup *)ocgs->get(idx);
+}
+
+OptionalContentGroup *OptionalContent::findOCG(Ref *ref) {
+ OptionalContentGroup *ocg;
+ int i;
+
+ for (i = 0; i < ocgs->getLength(); ++i) {
+ ocg = (OptionalContentGroup *)ocgs->get(i);
+ if (ocg->matches(ref)) {
+ return ocg;
+ }
+ }
+ return NULL;
+}
+
+GBool OptionalContent::evalOCObject(Object *obj, GBool *visible) {
+ OptionalContentGroup *ocg;
+ int policy;
+ Ref ref;
+ Object obj2, obj3, obj4, obj5;
+ int i;
+
+ if (obj->isNull()) {
+ return gFalse;
+ }
+ if (obj->isRef()) {
+ ref = obj->getRef();
+ if ((ocg = findOCG(&ref))) {
+ *visible = ocg->getState();
+ return gTrue;
+ }
+ }
+ obj->fetch(xref, &obj2);
+ if (obj2.isDict("OCMD")) {
+ if (obj2.dictLookup("VE", &obj3)->isArray()) {
+ *visible = evalOCVisibilityExpr(&obj3, 0);
+ obj3.free();
+ } else {
+ obj3.free();
+ policy = ocPolicyAnyOn;
+ if (obj2.dictLookup("P", &obj3)->isName()) {
+ if (obj3.isName("AllOn")) {
+ policy = ocPolicyAllOn;
+ } else if (obj3.isName("AnyOn")) {
+ policy = ocPolicyAnyOn;
+ } else if (obj3.isName("AnyOff")) {
+ policy = ocPolicyAnyOff;
+ } else if (obj3.isName("AllOff")) {
+ policy = ocPolicyAllOff;
+ }
+ }
+ obj3.free();
+ obj2.dictLookupNF("OCGs", &obj3);
+ ocg = NULL;
+ if (obj3.isRef()) {
+ ref = obj3.getRef();
+ ocg = findOCG(&ref);
+ }
+ if (ocg) {
+ *visible = (policy == ocPolicyAllOn || policy == ocPolicyAnyOn) ?
+ ocg->getState() : !ocg->getState();
+ } else {
+ *visible = gTrue;
+ if (obj3.fetch(xref, &obj4)->isArray()) {
+ for (i = 0; i < obj4.arrayGetLength(); ++i) {
+ obj4.arrayGetNF(i, &obj5);
+ if (obj5.isRef()) {
+ ref = obj5.getRef();
+ if ((ocg = findOCG(&ref))) {
+ switch (policy) {
+ case ocPolicyAllOn:
+ *visible = *visible && ocg->getState();
+ break;
+ case ocPolicyAnyOn:
+ *visible = *visible || ocg->getState();
+ break;
+ case ocPolicyAnyOff:
+ *visible = *visible || !ocg->getState();
+ break;
+ case ocPolicyAllOff:
+ *visible = *visible && !ocg->getState();
+ break;
+ }
+ }
+ }
+ obj5.free();
+ }
+ }
+ obj4.free();
+ }
+ obj3.free();
+ }
+ obj2.free();
+ return gTrue;
+ }
+ obj2.free();
+ return gFalse;
+}
+
+GBool OptionalContent::evalOCVisibilityExpr(Object *expr, int recursion) {
+ OptionalContentGroup *ocg;
+ Object expr2, op, obj;
+ Ref ref;
+ GBool ret;
+ int i;
+
+ if (recursion > visibilityExprRecursionLimit) {
+ error(errSyntaxError, -1,
+ "Loop detected in optional content visibility expression");
+ return gTrue;
+ }
+ if (expr->isRef()) {
+ ref = expr->getRef();
+ if ((ocg = findOCG(&ref))) {
+ return ocg->getState();
+ }
+ }
+ expr->fetch(xref, &expr2);
+ if (!expr2.isArray() || expr2.arrayGetLength() < 1) {
+ error(errSyntaxError, -1,
+ "Invalid optional content visibility expression");
+ expr2.free();
+ return gTrue;
+ }
+ expr2.arrayGet(0, &op);
+ if (op.isName("Not")) {
+ if (expr2.arrayGetLength() == 2) {
+ expr2.arrayGetNF(1, &obj);
+ ret = !evalOCVisibilityExpr(&obj, recursion + 1);
+ obj.free();
+ } else {
+ error(errSyntaxError, -1,
+ "Invalid optional content visibility expression");
+ ret = gTrue;
+ }
+ } else if (op.isName("And")) {
+ ret = gTrue;
+ for (i = 1; i < expr2.arrayGetLength() && ret; ++i) {
+ expr2.arrayGetNF(i, &obj);
+ ret = evalOCVisibilityExpr(&obj, recursion + 1);
+ obj.free();
+ }
+ } else if (op.isName("Or")) {
+ ret = gFalse;
+ for (i = 1; i < expr2.arrayGetLength() && !ret; ++i) {
+ expr2.arrayGetNF(i, &obj);
+ ret = evalOCVisibilityExpr(&obj, recursion + 1);
+ obj.free();
+ }
+ } else {
+ error(errSyntaxError, -1,
+ "Invalid optional content visibility expression");
+ ret = gTrue;
+ }
+ op.free();
+ expr2.free();
+ return ret;
+}
+
+//------------------------------------------------------------------------
+
+OptionalContentGroup *OptionalContentGroup::parse(Ref *refA, Object *obj) {
+ Unicode *nameA;
+ int nameLenA;
+ Object obj1, obj2, obj3;
+ GString *s;
+ OCUsageState viewStateA, printStateA;
+ int i;
+
+ if (!obj->isDict()) {
+ return NULL;
+ }
+ if (!obj->dictLookup("Name", &obj1)->isString()) {
+ error(errSyntaxError, -1, "Missing or invalid Name in OCG");
+ obj1.free();
+ return NULL;
+ }
+ s = obj1.getString();
+ if ((s->getChar(0) & 0xff) == 0xfe &&
+ (s->getChar(1) & 0xff) == 0xff) {
+ nameLenA = (s->getLength() - 2) / 2;
+ nameA = (Unicode *)gmallocn(nameLenA, sizeof(Unicode));
+ for (i = 0; i < nameLenA; ++i) {
+ nameA[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
+ (s->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ nameLenA = s->getLength();
+ nameA = (Unicode *)gmallocn(nameLenA, sizeof(Unicode));
+ for (i = 0; i < nameLenA; ++i) {
+ nameA[i] = pdfDocEncoding[s->getChar(i) & 0xff];
+ }
+ }
+ obj1.free();
+
+ viewStateA = printStateA = ocUsageUnset;
+ if (obj->dictLookup("Usage", &obj1)->isDict()) {
+ if (obj1.dictLookup("View", &obj2)->isDict()) {
+ if (obj2.dictLookup("ViewState", &obj3)->isName()) {
+ if (obj3.isName("ON")) {
+ viewStateA = ocUsageOn;
+ } else {
+ viewStateA = ocUsageOff;
+ }
+ }
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Print", &obj2)->isDict()) {
+ if (obj2.dictLookup("PrintState", &obj3)->isName()) {
+ if (obj3.isName("ON")) {
+ printStateA = ocUsageOn;
+ } else {
+ printStateA = ocUsageOff;
+ }
+ }
+ obj3.free();
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ return new OptionalContentGroup(refA, nameA, nameLenA,
+ viewStateA, printStateA);
+}
+
+OptionalContentGroup::OptionalContentGroup(Ref *refA, Unicode *nameA,
+ int nameLenA,
+ OCUsageState viewStateA,
+ OCUsageState printStateA) {
+ ref = *refA;
+ name = nameA;
+ nameLen = nameLenA;
+ viewState = viewStateA;
+ printState = printStateA;
+ state = gTrue;
+}
+
+OptionalContentGroup::~OptionalContentGroup() {
+ gfree(name);
+}
+
+GBool OptionalContentGroup::matches(Ref *refA) {
+ return refA->num == ref.num && refA->gen == ref.gen;
+}
+
+//------------------------------------------------------------------------
+
+OCDisplayNode *OCDisplayNode::parse(Object *obj, OptionalContent *oc,
+ XRef *xref, int recursion) {
+ Object obj2, obj3;
+ Ref ref;
+ OptionalContentGroup *ocgA;
+ OCDisplayNode *node, *child;
+ int i;
+
+ if (recursion > displayNodeRecursionLimit) {
+ error(errSyntaxError, -1, "Loop detected in optional content order");
+ return NULL;
+ }
+ if (obj->isRef()) {
+ ref = obj->getRef();
+ if ((ocgA = oc->findOCG(&ref))) {
+ return new OCDisplayNode(ocgA);
+ }
+ }
+ obj->fetch(xref, &obj2);
+ if (!obj2.isArray()) {
+ obj2.free();
+ return NULL;
+ }
+ i = 0;
+ if (obj2.arrayGetLength() >= 1) {
+ if (obj2.arrayGet(0, &obj3)->isString()) {
+ node = new OCDisplayNode(obj3.getString());
+ i = 1;
+ } else {
+ node = new OCDisplayNode();
+ }
+ obj3.free();
+ } else {
+ node = new OCDisplayNode();
+ }
+ for (; i < obj2.arrayGetLength(); ++i) {
+ obj2.arrayGetNF(i, &obj3);
+ if ((child = OCDisplayNode::parse(&obj3, oc, xref, recursion + 1))) {
+ if (!child->ocg && !child->name && node->getNumChildren() > 0) {
+ node->getChild(node->getNumChildren() - 1)->
+ addChildren(child->takeChildren());
+ delete child;
+ } else {
+ node->addChild(child);
+ }
+ }
+ obj3.free();
+ }
+ obj2.free();
+ return node;
+}
+
+OCDisplayNode::OCDisplayNode() {
+ name = NULL;
+ nameLen = 0;
+ ocg = NULL;
+ children = NULL;
+}
+
+OCDisplayNode::OCDisplayNode(GString *nameA) {
+ int i;
+
+ if ((nameA->getChar(0) & 0xff) == 0xfe &&
+ (nameA->getChar(1) & 0xff) == 0xff) {
+ nameLen = (nameA->getLength() - 2) / 2;
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ for (i = 0; i < nameLen; ++i) {
+ name[i] = ((nameA->getChar(2 + 2*i) & 0xff) << 8) |
+ (nameA->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ nameLen = nameA->getLength();
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ for (i = 0; i < nameLen; ++i) {
+ name[i] = pdfDocEncoding[nameA->getChar(i) & 0xff];
+ }
+ }
+ ocg = NULL;
+ children = NULL;
+}
+
+OCDisplayNode::OCDisplayNode(OptionalContentGroup *ocgA) {
+ nameLen = ocgA->getNameLength();
+ if (nameLen) {
+ name = (Unicode *)gmallocn(nameLen, sizeof(Unicode));
+ memcpy(name, ocgA->getName(), nameLen * sizeof(Unicode));
+ } else {
+ name = NULL;
+ }
+ ocg = ocgA;
+ children = NULL;
+}
+
+void OCDisplayNode::addChild(OCDisplayNode *child) {
+ if (!children) {
+ children = new GList();
+ }
+ children->append(child);
+}
+
+void OCDisplayNode::addChildren(GList *childrenA) {
+ if (!children) {
+ children = new GList();
+ }
+ children->append(childrenA);
+ delete childrenA;
+}
+
+GList *OCDisplayNode::takeChildren() {
+ GList *childrenA;
+
+ childrenA = children;
+ children = NULL;
+ return childrenA;
+}
+
+OCDisplayNode::~OCDisplayNode() {
+ gfree(name);
+ if (children) {
+ deleteGList(children, OCDisplayNode);
+ }
+}
+
+int OCDisplayNode::getNumChildren() {
+ if (!children) {
+ return 0;
+ }
+ return children->getLength();
+}
+
+OCDisplayNode *OCDisplayNode::getChild(int idx) {
+ return (OCDisplayNode *)children->get(idx);
+}
diff --git a/xpdf/OptionalContent.h b/xpdf/OptionalContent.h
new file mode 100644
index 0000000..82d3e0e
--- /dev/null
+++ b/xpdf/OptionalContent.h
@@ -0,0 +1,132 @@
+//========================================================================
+//
+// OptionalContent.h
+//
+// Copyright 2008 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef OPTIONALCONTENT_H
+#define OPTIONALCONTENT_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "CharTypes.h"
+
+class GString;
+class GList;
+class PDFDoc;
+class XRef;
+class OptionalContentGroup;
+class OCDisplayNode;
+
+//------------------------------------------------------------------------
+
+class OptionalContent {
+public:
+
+ OptionalContent(PDFDoc *doc);
+ ~OptionalContent();
+
+ // Walk the list of optional content groups.
+ int getNumOCGs();
+ OptionalContentGroup *getOCG(int idx);
+
+ // Find an OCG by indirect reference.
+ OptionalContentGroup *findOCG(Ref *ref);
+
+ // Get the root node of the optional content group display tree
+ // (which does not necessarily include all of the OCGs).
+ OCDisplayNode *getDisplayRoot() { return display; }
+
+ // Evaluate an optional content object -- either an OCG or an OCMD.
+ // If <obj> is a valid OCG or OCMD, sets *<visible> and returns
+ // true; otherwise returns false.
+ GBool evalOCObject(Object *obj, GBool *visible);
+
+private:
+
+ GBool evalOCVisibilityExpr(Object *expr, int recursion);
+
+ XRef *xref;
+ GList *ocgs; // all OCGs [OptionalContentGroup]
+ OCDisplayNode *display; // root node of display tree
+};
+
+//------------------------------------------------------------------------
+
+// Values from the optional content usage dictionary.
+enum OCUsageState {
+ ocUsageOn,
+ ocUsageOff,
+ ocUsageUnset
+};
+
+//------------------------------------------------------------------------
+
+class OptionalContentGroup {
+public:
+
+ static OptionalContentGroup *parse(Ref *refA, Object *obj);
+ ~OptionalContentGroup();
+
+ GBool matches(Ref *refA);
+
+ Unicode *getName() { return name; }
+ int getNameLength() { return nameLen; }
+ OCUsageState getViewState() { return viewState; }
+ OCUsageState getPrintState() { return printState; }
+ GBool getState() { return state; }
+ void setState(GBool stateA) { state = stateA; }
+
+private:
+
+ OptionalContentGroup(Ref *refA, Unicode *nameA, int nameLenA,
+ OCUsageState viewStateA, OCUsageState printStateA);
+
+ Ref ref;
+ Unicode *name;
+ int nameLen;
+ OCUsageState viewState, // suggested state when viewing
+ printState; // suggested state when printing
+ GBool state; // current state (on/off)
+};
+
+//------------------------------------------------------------------------
+
+class OCDisplayNode {
+public:
+
+ static OCDisplayNode *parse(Object *obj, OptionalContent *oc, XRef *xref,
+ int recursion = 0);
+ OCDisplayNode();
+ ~OCDisplayNode();
+
+ Unicode *getName() { return name; }
+ int getNameLength() { return nameLen; }
+ OptionalContentGroup *getOCG() { return ocg; }
+ int getNumChildren();
+ OCDisplayNode *getChild(int idx);
+
+private:
+
+ OCDisplayNode(GString *nameA);
+ OCDisplayNode(OptionalContentGroup *ocgA);
+ void addChild(OCDisplayNode *child);
+ void addChildren(GList *childrenA);
+ GList *takeChildren();
+
+ Unicode *name; // display name (may be NULL)
+ int nameLen;
+ OptionalContentGroup *ocg; // NULL for display labels
+ GList *children; // NULL if there are no children
+ // [OCDisplayNode]
+};
+
+#endif
diff --git a/xpdf/Outline.cc b/xpdf/Outline.cc
index 39e89a3..30ca85d 100644
--- a/xpdf/Outline.cc
+++ b/xpdf/Outline.cc
@@ -15,6 +15,7 @@
#include "gmem.h"
#include "GString.h"
#include "GList.h"
+#include "Error.h"
#include "Link.h"
#include "PDFDocEncoding.h"
#include "Outline.h"
@@ -28,9 +29,11 @@ Outline::Outline(Object *outlineObj, XRef *xref) {
if (!outlineObj->isDict()) {
return;
}
- items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
- outlineObj->dictLookupNF("Last", &last),
- xref);
+ outlineObj->dictLookupNF("First", &first);
+ outlineObj->dictLookupNF("Last", &last);
+ if (first.isRef() && last.isRef()) {
+ items = OutlineItem::readItemList(&first, &last, xref);
+ }
first.free();
last.free();
}
@@ -116,11 +119,15 @@ GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
GList *items;
OutlineItem *item;
Object obj;
- Object *p;
+ Object *p, *refObj;
+ int i;
items = new GList();
+ if (!firstItemRef->isRef() || !lastItemRef->isRef()) {
+ return items;
+ }
p = firstItemRef;
- while (p->isRef()) {
+ do {
if (!p->fetch(xrefA, &obj)->isDict()) {
obj.free();
break;
@@ -128,12 +135,25 @@ GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
item = new OutlineItem(obj.getDict(), xrefA);
obj.free();
items->append(item);
- if (p->getRef().num == lastItemRef->getRef().num &&
- p->getRef().gen == lastItemRef->getRef().gen) {
+ if (p->getRefNum() == lastItemRef->getRef().num &&
+ p->getRefGen() == lastItemRef->getRef().gen) {
break;
}
p = &item->nextRef;
- }
+ if (!p->isRef()) {
+ break;
+ }
+ for (i = 0; i < items->getLength(); ++i) {
+ refObj = (i == 0) ? firstItemRef
+ : &((OutlineItem *)items->get(i - 1))->nextRef;
+ if (refObj->getRefNum() == p->getRefNum() &&
+ refObj->getRefGen() == p->getRefGen()) {
+ error(errSyntaxError, -1, "Loop detected in outline item list");
+ p = NULL;
+ break;
+ }
+ }
+ } while (p);
return items;
}
diff --git a/xpdf/OutputDev.cc b/xpdf/OutputDev.cc
index 8d4763b..d2ef286 100644
--- a/xpdf/OutputDev.cc
+++ b/xpdf/OutputDev.cc
@@ -65,6 +65,7 @@ void OutputDev::updateAll(GfxState *state) {
updateStrokeOpacity(state);
updateFillOverprint(state);
updateStrokeOverprint(state);
+ updateOverprintMode(state);
updateTransfer(state);
updateFont(state);
}
@@ -89,6 +90,13 @@ void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
}
}
+void OutputDev::setSoftMaskFromImageMask(GfxState *state,
+ Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg) {
+ drawImageMask(state, ref, str, width, height, invert, inlineImg);
+}
+
void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg) {
diff --git a/xpdf/OutputDev.h b/xpdf/OutputDev.h
index 27dc0dd..138aa34 100644
--- a/xpdf/OutputDev.h
+++ b/xpdf/OutputDev.h
@@ -19,6 +19,7 @@
#include "CharTypes.h"
class GString;
+class Gfx;
class GfxState;
struct GfxColor;
class GfxColorSpace;
@@ -76,6 +77,11 @@ public:
// Does this device need non-text content?
virtual GBool needNonText() { return gTrue; }
+ // Does this device require incCharCount to be called for text on
+ // non-shown layers?
+ virtual GBool needCharCount() { return gFalse; }
+
+
//----- initialization and control
// Set default transform matrix.
@@ -88,7 +94,7 @@ public:
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 printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL)
{ return gTrue; }
@@ -135,6 +141,7 @@ public:
virtual void updateStrokeOpacity(GfxState *state) {}
virtual void updateFillOverprint(GfxState *state) {}
virtual void updateStrokeOverprint(GfxState *state) {}
+ virtual void updateOverprintMode(GfxState *state) {}
virtual void updateTransfer(GfxState *state) {}
//----- update text state
@@ -147,12 +154,14 @@ public:
virtual void updateHorizScaling(GfxState *state) {}
virtual void updateTextPos(GfxState *state) {}
virtual void updateTextShift(GfxState *state, double shift) {}
+ virtual void saveTextPos(GfxState *state) {}
+ virtual void restoreTextPos(GfxState *state) {}
//----- path painting
virtual void stroke(GfxState *state) {}
virtual void fill(GfxState *state) {}
virtual void eoFill(GfxState *state) {}
- virtual void tilingPatternFill(GfxState *state, Object *str,
+ virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
int paintType, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
@@ -185,11 +194,18 @@ public:
CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state) {}
virtual void endTextObject(GfxState *state) {}
+ virtual void incCharCount(int nChars) {}
+ virtual void beginActualText(GfxState *state, Unicode *u, int uLen) {}
+ virtual void endActualText(GfxState *state) {}
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
+ virtual void setSoftMaskFromImageMask(GfxState *state,
+ Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg);
virtual void drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
@@ -234,11 +250,10 @@ public:
virtual void clearSoftMask(GfxState *state) {}
//----- links
- virtual void processLink(Link *link, Catalog *catalog) {}
+ virtual void processLink(Link *link) {}
#if 1 //~tmp: turn off anti-aliasing temporarily
- virtual GBool getVectorAntialias() { return gFalse; }
- virtual void setVectorAntialias(GBool vaa) {}
+ virtual void setInShading(GBool sh) {}
#endif
private:
diff --git a/xpdf/PDFCore.cc b/xpdf/PDFCore.cc
index fb3df3f..6435815 100644
--- a/xpdf/PDFCore.cc
+++ b/xpdf/PDFCore.cc
@@ -89,6 +89,7 @@ PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA,
maxPageW = totalDocH = 0;
pageY = NULL;
topPage = 0;
+ midPage = 0;
scrollX = scrollY = 0;
zoom = defZoom;
dpi = 0;
@@ -99,6 +100,8 @@ PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA,
selectULY = selectLRY = 0;
dragging = gFalse;
lastDragLeft = lastDragTop = gTrue;
+ selectXorColor[0] = selectXorColor[1] = selectXorColor[2] = 0;
+ splashColorXor(selectXorColor, paperColorA);
historyCur = pdfHistorySize - 1;
historyBLen = historyFLen = 0;
@@ -196,6 +199,7 @@ int PDFCore::loadFile2(PDFDoc *newDoc) {
// nothing displayed yet
topPage = -99;
+ midPage = -99;
while (pages->getLength() > 0) {
delete (PDFCorePage *)pages->del(0);
}
@@ -231,6 +235,7 @@ void PDFCore::clear() {
// no page displayed
topPage = -99;
+ midPage = -99;
while (pages->getLength() > 0) {
delete (PDFCorePage *)pages->del(0);
}
@@ -255,6 +260,7 @@ PDFDoc *PDFCore::takeDoc(GBool redraw) {
// no page displayed
topPage = -99;
+ midPage = -99;
while (pages->getLength() > 0) {
delete (PDFCorePage *)pages->del(0);
}
@@ -289,7 +295,8 @@ void PDFCore::displayPage(int topPageA, double zoomA, int rotateA,
dragging = gFalse;
lastDragLeft = lastDragTop = gTrue;
- update(topPageA, scrollXA, scrollYA, zoomA, rotateA, gTrue, addToHist);
+ update(topPageA, scrollXA, scrollYA, zoomA, rotateA, gTrue, addToHist,
+ gTrue);
}
void PDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA,
@@ -313,61 +320,84 @@ void PDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA,
case destXYZ:
cvtUserToDev(topPageA, dest->getLeft(), dest->getTop(), &dx, &dy);
scrollXA = dest->getChangeLeft() ? dx : scrollX;
- if (dest->getChangeTop()) {
- scrollYA = dy;
- } else {
+ if (continuousMode) {
if (topPage <= 0) {
- scrollYA = 0;
- } else if (continuousMode) {
- scrollYA = scrollY - pageY[topPage - 1];
+ scrollYA = -1;
+ } else if (dest->getChangeTop()) {
+ scrollYA = pageY[topPageA - 1] + dy;
} else {
+ scrollYA = pageY[topPageA - 1] + (scrollY - pageY[topPage - 1]);
+ }
+ } else {
+ if (dest->getChangeTop()) {
+ scrollYA = dy;
+ } else if (topPage > 0) {
scrollYA = scrollY;
+ } else {
+ scrollYA = 0;
}
}
- if (continuousMode && topPage > 0) {
- scrollYA += pageY[topPageA - 1];
- }
- //~ what is the zoom parameter?
+ //~ this doesn't currently handle the zoom parameter
+ update(topPageA, scrollXA, scrollYA, zoom, rotate, gFalse,
+ addToHist && topPageA != topPage, gTrue);
break;
case destFit:
case destFitB:
- //~ do fit
scrollXA = 0;
scrollYA = continuousMode ? -1 : 0;
+ update(topPageA, scrollXA, scrollYA, zoomPage, rotate, gFalse,
+ addToHist && topPageA != topPage, gTrue);
break;
case destFitH:
case destFitBH:
- //~ do fit
+ //~ do fit: need a function similar to zoomToRect which will
+ //~ accept an absolute top coordinate (rather than centering)
+ scrollXA = 0;
cvtUserToDev(topPageA, 0, dest->getTop(), &dx, &dy);
- if (continuousMode && topPage > 0) {
- dy += pageY[topPageA - 1];
+ if (continuousMode) {
+ if (topPage <= 0) {
+ scrollYA = -1;
+ } else if (dest->getChangeTop()) {
+ scrollYA = pageY[topPageA - 1] + dy;
+ } else {
+ scrollYA = pageY[topPageA - 1] + (scrollY - pageY[topPage - 1]);
+ }
+ } else {
+ if (dest->getChangeTop()) {
+ scrollYA = dy;
+ } else if (topPage > 0) {
+ scrollYA = scrollY;
+ } else {
+ scrollYA = 0;
+ }
}
- scrollXA = 0;
- scrollYA = dy;
+ update(topPageA, scrollXA, scrollYA, zoom, rotate, gFalse,
+ addToHist && topPageA != topPage, gTrue);
break;
case destFitV:
case destFitBV:
- //~ do fit
- cvtUserToDev(topPageA, dest->getLeft(), 0, &dx, &dy);
- scrollXA = dx;
+ //~ do fit: need a function similar to zoomToRect which will
+ //~ accept an absolute left coordinate (rather than centering)
+ if (dest->getChangeLeft()) {
+ cvtUserToDev(topPageA, dest->getLeft(), 0, &dx, &dy);
+ scrollXA = dx;
+ } else {
+ scrollXA = scrollX;
+ }
scrollYA = continuousMode ? -1 : 0;
+ update(topPageA, scrollXA, scrollYA, zoom, rotate, gFalse,
+ addToHist && topPageA != topPage, gTrue);
break;
case destFitR:
- //~ do fit
- cvtUserToDev(topPageA, dest->getLeft(), dest->getTop(), &dx, &dy);
- if (continuousMode && topPage > 0) {
- dy += pageY[topPageA - 1];
- }
- scrollXA = dx;
- scrollYA = dy;
+ zoomToRect(topPageA, dest->getLeft(), dest->getTop(),
+ dest->getRight(), dest->getBottom());
break;
}
- update(topPageA, scrollXA, scrollYA, zoom, rotate, gFalse,
- addToHist && topPageA != topPage);
}
void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
- double zoomA, int rotateA, GBool force, GBool addToHist) {
+ double zoomA, int rotateA, GBool force,
+ GBool addToHist, GBool adjustScrollX) {
double hDPI, vDPI, dpiA, uw, uh, ut;
int w, h, t, x0, x1, y0, y1, x, y;
int rot;
@@ -375,7 +405,6 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
PDFCoreTile *tile;
PDFCorePage *page;
PDFHistory *hist;
- SplashColor xorColor;
GBool needUpdate;
int i, j;
@@ -443,7 +472,8 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
// object
if (force || pages->getLength() == 0 ||
(!continuousMode && topPageA != topPage) ||
- zoomA != zoom || dpiA != dpi || rotateA != rotate) {
+ fabs(zoomA - zoom) > 1e-8 || fabs(dpiA - dpi) > 1e-8 ||
+ rotateA != rotate) {
needUpdate = gTrue;
setSelection(0, 0, 0, 0, 0);
while (pages->getLength() > 0) {
@@ -488,9 +518,8 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
} else {
// erase the selection
if (selectULX != selectLRX && selectULY != selectLRY) {
- xorColor[0] = xorColor[1] = xorColor[2] = 0xff;
xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY,
- new SplashSolidColor(xorColor));
+ new SplashSolidColor(selectXorColor));
}
}
if (continuousMode) {
@@ -499,6 +528,7 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
page = (PDFCorePage *)pages->get(0);
}
topPage = topPageA;
+ midPage = topPage;
// adjust the scroll position
scrollX = scrollXA;
@@ -507,6 +537,22 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
} else {
scrollY = scrollYA;
}
+ if (continuousMode && adjustScrollX) {
+ rot = rotate + doc->getPageRotate(topPage);
+ if (rot >= 360) {
+ rot -= 360;
+ } else if (rot < 0) {
+ rot += 360;
+ }
+ if (rot == 90 || rot == 270) {
+ w = (int)((doc->getPageCropHeight(topPage) * dpi) / 72 + 0.5);
+ } else {
+ w = (int)((doc->getPageCropWidth(topPage) * dpi) / 72 + 0.5);
+ }
+ if (scrollX < (maxPageW - w) / 2) {
+ scrollX = (maxPageW - w) / 2;
+ }
+ }
w = continuousMode ? maxPageW : page->w;
if (scrollX > w - drawAreaWidth) {
scrollX = w - drawAreaWidth;
@@ -538,6 +584,12 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
}
topPage = i - 1;
for (i = topPage + 1; i <= doc->getNumPages(); ++i) {
+ if (pageY[i-1] > scrollY + drawAreaHeight / 2) {
+ break;
+ }
+ }
+ midPage = i - 1;
+ for (i = midPage + 1; i <= doc->getNumPages(); ++i) {
if (pageY[i-1] > scrollY + drawAreaHeight + drawAreaHeight / 2) {
break;
}
@@ -691,9 +743,8 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA,
// redraw the selection
if (selectULX != selectLRX && selectULY != selectLRY) {
- xorColor[0] = xorColor[1] = xorColor[2] = 0xff;
xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY,
- new SplashSolidColor(xorColor));
+ new SplashSolidColor(selectXorColor));
}
// redraw the window
@@ -736,14 +787,16 @@ void PDFCore::addPage(int pg, int rot) {
tileW = 1500;
}
if (tileW > w) {
- tileW = w;
+ // tileW can't be zero -- we end up with div-by-zero problems
+ tileW = w ? w : 1;
}
tileH = 2 * drawAreaHeight;
if (tileH < 1500) {
tileH = 1500;
}
if (tileH > h) {
- tileH = h;
+ // tileH can't be zero -- we end up with div-by-zero problems
+ tileH = h ? h : 1;
}
page = new PDFCorePage(pg, w, h, tileW, tileH);
for (i = 0;
@@ -840,7 +893,7 @@ void PDFCore::needTile(PDFCorePage *page, int x, int y) {
page->links = doc->getLinks(page->page);
}
if (!page->text) {
- if ((textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse))) {
+ if ((textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse))) {
doc->displayPage(textOut, page->page, dpi, dpi, rotate,
gFalse, gTrue, gFalse);
page->text = textOut->takeText();
@@ -870,7 +923,7 @@ GBool PDFCore::gotoNextPage(int inc, GBool top) {
} else {
scrollYA = scrollY;
}
- update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue);
+ update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue, gTrue);
return gTrue;
}
@@ -895,7 +948,7 @@ GBool PDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) {
} else {
scrollYA = scrollY;
}
- update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue);
+ update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue, gTrue);
return gTrue;
}
@@ -931,7 +984,7 @@ GBool PDFCore::goForward() {
}
pg = history[historyCur].page;
update(pg, scrollX, continuousMode ? -1 : scrollY,
- zoom, rotate, gFalse, gFalse);
+ zoom, rotate, gFalse, gFalse, gTrue);
return gTrue;
}
@@ -953,7 +1006,7 @@ GBool PDFCore::goBackward() {
}
pg = history[historyCur].page;
update(pg, scrollX, continuousMode ? -1 : scrollY,
- zoom, rotate, gFalse, gFalse);
+ zoom, rotate, gFalse, gFalse, gTrue);
return gTrue;
}
@@ -1000,6 +1053,7 @@ void PDFCore::scrollPageUp() {
void PDFCore::scrollPageDown() {
if (!continuousMode &&
+ pages->getLength() > 0 &&
scrollY >= ((PDFCorePage *)pages->get(0))->h - drawAreaHeight) {
gotoNextPage(1, gTrue);
} else {
@@ -1008,11 +1062,11 @@ void PDFCore::scrollPageDown() {
}
void PDFCore::scrollTo(int x, int y) {
- update(topPage, x, y < 0 ? 0 : y, zoom, rotate, gFalse, gFalse);
+ update(topPage, x, y < 0 ? 0 : y, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToLeftEdge() {
- update(topPage, 0, scrollY, zoom, rotate, gFalse, gFalse);
+ update(topPage, 0, scrollY, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToRightEdge() {
@@ -1020,14 +1074,14 @@ void PDFCore::scrollToRightEdge() {
page = (PDFCorePage *)pages->get(0);
update(topPage, page->w - drawAreaWidth, scrollY,
- zoom, rotate, gFalse, gFalse);
+ zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToTopEdge() {
int y;
y = continuousMode ? pageY[topPage - 1] : 0;
- update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse);
+ update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToBottomEdge() {
@@ -1046,14 +1100,14 @@ void PDFCore::scrollToBottomEdge() {
} else {
y = page->h - drawAreaHeight;
}
- update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse);
+ update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToTopLeft() {
int y;
y = continuousMode ? pageY[topPage - 1] : 0;
- update(topPage, 0, y, zoom, rotate, gFalse, gFalse);
+ update(topPage, 0, y, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::scrollToBottomRight() {
@@ -1073,7 +1127,7 @@ void PDFCore::scrollToBottomRight() {
} else {
y = page->h - drawAreaHeight;
}
- update(topPage, x, y, zoom, rotate, gFalse, gFalse);
+ update(topPage, x, y, zoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::zoomToRect(int pg, double ulx, double uly,
@@ -1117,7 +1171,7 @@ void PDFCore::zoomToRect(int pg, double ulx, double uly,
sy += (int)(ry * (pageY[pg - 1] - u)) + u;
}
}
- update(pg, sx, sy, newZoom, rotate, gFalse, gFalse);
+ update(pg, sx, sy, newZoom, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::zoomCentered(double zoomA) {
@@ -1204,7 +1258,7 @@ void PDFCore::zoomCentered(double zoomA) {
- drawAreaHeight / 2;
}
- update(topPage, sx, sy, zoomA, rotate, gFalse, gFalse);
+ update(topPage, sx, sy, zoomA, rotate, gFalse, gFalse, gFalse);
}
// Zoom so that the current page(s) fill the window width. Maintain
@@ -1284,16 +1338,21 @@ void PDFCore::zoomToCurrentWidth() {
- drawAreaHeight / 2;
}
- update(topPage, sx, sy, (dpi1 * 100) / 72, rotate, gFalse, gFalse);
+ update(topPage, sx, sy, (dpi1 * 100) / 72, rotate, gFalse, gFalse, gFalse);
}
void PDFCore::setContinuousMode(GBool cm) {
if (continuousMode != cm) {
continuousMode = cm;
- update(topPage, scrollX, -1, zoom, rotate, gTrue, gFalse);
+ update(topPage, scrollX, -1, zoom, rotate, gTrue, gFalse, gTrue);
}
}
+void PDFCore::setSelectionColor(SplashColor color) {
+ splashColorCopy(selectXorColor, color);
+ splashColorXor(selectXorColor, paperColor);
+}
+
void PDFCore::setSelection(int newSelectPage,
int newSelectULX, int newSelectULY,
int newSelectLRX, int newSelectLRY) {
@@ -1301,7 +1360,6 @@ void PDFCore::setSelection(int newSelectPage,
GBool haveSel, newHaveSel;
GBool needRedraw, needScroll;
GBool moveLeft, moveRight, moveTop, moveBottom;
- SplashColor xorColor;
PDFCorePage *page;
@@ -1311,18 +1369,16 @@ void PDFCore::setSelection(int newSelectPage,
// erase old selection on off-screen bitmap
needRedraw = gFalse;
if (haveSel) {
- xorColor[0] = xorColor[1] = xorColor[2] = 0xff;
xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY,
- new SplashSolidColor(xorColor));
+ new SplashSolidColor(selectXorColor));
needRedraw = gTrue;
}
// draw new selection on off-screen bitmap
if (newHaveSel) {
- xorColor[0] = xorColor[1] = xorColor[2] = 0xff;
xorRectangle(newSelectPage, newSelectULX, newSelectULY,
newSelectLRX, newSelectLRY,
- new SplashSolidColor(xorColor));
+ new SplashSolidColor(selectXorColor));
needRedraw = gTrue;
}
@@ -1577,7 +1633,7 @@ GString *PDFCore::extractText(int pg, double xMin, double yMin,
}
s = page->text->getText(x0, y0, x1, y1);
} else {
- textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
+ textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse);
if (textOut->isOk()) {
doc->displayPage(textOut, pg, dpi, dpi, rotate, gFalse, gTrue, gFalse);
textOut->cvtUserToDev(xMin, yMin, &x0, &y0);
@@ -1598,26 +1654,27 @@ GString *PDFCore::extractText(int pg, double xMin, double yMin,
}
GBool PDFCore::find(char *s, GBool caseSensitive, GBool next, GBool backward,
- GBool onePageOnly) {
+ GBool wholeWord, GBool onePageOnly) {
Unicode *u;
int len, i;
GBool ret;
// convert to Unicode
- len = strlen(s);
+ len = (int)strlen(s);
u = (Unicode *)gmallocn(len, sizeof(Unicode));
for (i = 0; i < len; ++i) {
u[i] = (Unicode)(s[i] & 0xff);
}
- ret = findU(u, len, caseSensitive, next, backward, onePageOnly);
+ ret = findU(u, len, caseSensitive, next, backward, wholeWord, onePageOnly);
gfree(u);
return ret;
}
GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly) {
+ GBool next, GBool backward, GBool wholeWord,
+ GBool onePageOnly) {
TextOutputDev *textOut;
double xMin, yMin, xMax, yMax;
PDFCorePage *page;
@@ -1656,7 +1713,7 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
page = findPage(pg);
}
if (page->text->findText(u, len, startAtTop, gTrue, startAtLast, gFalse,
- caseSensitive, backward,
+ caseSensitive, backward, wholeWord,
&xMin, &yMin, &xMax, &yMax)) {
goto found;
}
@@ -1664,7 +1721,7 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
if (!onePageOnly) {
// search following/previous pages
- textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
+ textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse);
if (!textOut->isOk()) {
delete textOut;
goto notFound;
@@ -1674,7 +1731,7 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
pg += backward ? -1 : 1) {
doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse);
if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
- caseSensitive, backward,
+ caseSensitive, backward, wholeWord,
&xMin, &yMin, &xMax, &yMax)) {
delete textOut;
goto foundPage;
@@ -1687,7 +1744,7 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
pg += backward ? -1 : 1) {
doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse);
if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
- caseSensitive, backward,
+ caseSensitive, backward, wholeWord,
&xMin, &yMin, &xMax, &yMax)) {
delete textOut;
goto foundPage;
@@ -1709,7 +1766,7 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
yMax = selectLRY;
}
if (page->text->findText(u, len, gTrue, gFalse, gFalse, stopAtLast,
- caseSensitive, backward,
+ caseSensitive, backward, wholeWord,
&xMin, &yMin, &xMax, &yMax)) {
goto found;
}
@@ -1722,10 +1779,11 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive,
// found on a different page
foundPage:
- update(pg, scrollX, continuousMode ? -1 : 0, zoom, rotate, gFalse, gTrue);
+ update(pg, scrollX, continuousMode ? -1 : 0, zoom, rotate, gFalse, gTrue,
+ gTrue);
page = findPage(pg);
if (!page->text->findText(u, len, gTrue, gTrue, gFalse, gFalse,
- caseSensitive, backward,
+ caseSensitive, backward, wholeWord,
&xMin, &yMin, &xMax, &yMax)) {
// this can happen if coalescing is bad
goto notFound;
@@ -1752,6 +1810,9 @@ GBool PDFCore::cvtWindowToUser(int xw, int yw,
page = (PDFCorePage *)pages->get(i);
if (xw >= page->xDest && xw < page->xDest + page->w &&
yw >= page->yDest && yw < page->yDest + page->h) {
+ if (page->tiles->getLength() == 0) {
+ break;
+ }
tile = (PDFCoreTile *)page->tiles->get(0);
*pg = page->page;
xw -= tile->xDest;
@@ -1871,7 +1932,7 @@ void PDFCore::cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu) {
void PDFCore::setReverseVideo(GBool reverseVideoA) {
out->setReverseVideo(reverseVideoA);
- update(topPage, scrollX, scrollY, zoom, rotate, gTrue, gFalse);
+ update(topPage, scrollX, scrollY, zoom, rotate, gTrue, gFalse, gFalse);
}
LinkAction *PDFCore::findLink(int pg, double x, double y) {
@@ -1910,11 +1971,11 @@ void PDFCore::redrawCbk(void *data, int x0, int y0, int x1, int y1,
// the bitmap created by Gfx and SplashOutputDev can be a slightly
// different size due to rounding errors
- if (x1 >= core->curTile->xMax) {
- x1 = core->curTile->xMax - 1;
+ if (x1 >= core->curTile->xMax - core->curTile->xMin) {
+ x1 = core->curTile->xMax - core->curTile->xMin - 1;
}
- if (y1 >= core->curTile->yMax) {
- y1 = core->curTile->yMax - 1;
+ if (y1 >= core->curTile->yMax - core->curTile->yMin) {
+ y1 = core->curTile->yMax - core->curTile->yMin - 1;
}
core->clippedRedrawRect(core->curTile, x0, y0,
diff --git a/xpdf/PDFCore.h b/xpdf/PDFCore.h
index 013256d..264756f 100644
--- a/xpdf/PDFCore.h
+++ b/xpdf/PDFCore.h
@@ -160,7 +160,8 @@ public:
// Update the display, given the specified parameters.
virtual void update(int topPageA, int scrollXA, int scrollYA,
- double zoomA, int rotateA, GBool force, GBool addToHist);
+ double zoomA, int rotateA, GBool force,
+ GBool addToHist, GBool adjustScrollX);
//----- page/position changes
@@ -192,6 +193,9 @@ public:
//----- selection
+ // Selection color.
+ void setSelectionColor(SplashColor color);
+
// Current selected region.
void setSelection(int newSelectPage,
int newSelectULX, int newSelectULY,
@@ -207,9 +211,10 @@ public:
//----- find
virtual GBool find(char *s, GBool caseSensitive, GBool next, GBool backward,
- GBool onePageOnly);
+ GBool wholeWord, GBool onePageOnly);
virtual GBool findU(Unicode *u, int len, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly);
+ GBool next, GBool backward, GBool wholeWord,
+ GBool onePageOnly);
//----- coordinate conversion
@@ -225,6 +230,10 @@ public:
void cvtDevToWindow(int pg, int xd, int yd, int *xw, int *yw);
void cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu);
+ //----- password dialog
+
+ virtual GString *getPassword() { return NULL; }
+
//----- misc access
PDFDoc *getDoc() { return doc; }
@@ -284,6 +293,7 @@ protected:
int *pageY; // top coordinates for each page (only used
// in continuous mode)
int topPage; // page at top of window
+ int midPage; // page at middle of window
int scrollX, scrollY; // offset from top left corner of topPage
// to top left corner of window
double zoom; // current zoom level, in percent of 72 dpi
@@ -298,6 +308,7 @@ protected:
GBool dragging; // set while selection is being dragged
GBool lastDragLeft; // last dragged selection edge was left/right
GBool lastDragTop; // last dragged selection edge was top/bottom
+ SplashColor selectXorColor; // selection xor color
PDFHistory // page history queue
history[pdfHistorySize];
diff --git a/xpdf/PDFDoc.cc b/xpdf/PDFDoc.cc
index c559eef..b20ef2c 100644
--- a/xpdf/PDFDoc.cc
+++ b/xpdf/PDFDoc.cc
@@ -36,6 +36,7 @@
#ifndef DISABLE_OUTLINE
#include "Outline.h"
#endif
+#include "OptionalContent.h"
#include "PDFDoc.h"
//------------------------------------------------------------------------
@@ -48,14 +49,17 @@
//------------------------------------------------------------------------
PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
+ GString *userPassword, PDFCore *coreA) {
Object obj;
GString *fileName1, *fileName2;
+#ifdef WIN32
+ int n, i;
+#endif
ok = gFalse;
errCode = errNone;
- guiData = guiDataA;
+ core = coreA;
file = NULL;
str = NULL;
@@ -64,16 +68,25 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
+ optContent = NULL;
fileName = fileNameA;
- fileName1 = fileName;
+#ifdef WIN32
+ n = fileName->getLength();
+ fileNameU = (wchar_t *)gmallocn(n + 1, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameU[i] = (wchar_t)(fileName->getChar(i) & 0xff);
+ }
+ fileNameU[n] = L'\0';
+#endif
+ fileName1 = fileName;
// try to open file
fileName2 = NULL;
#ifdef VMS
if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
- error(-1, "Couldn't open file '%s'", fileName1->getCString());
+ error(errIO, -1, "Couldn't open file '{0:t}'", fileName1);
errCode = errOpenFile;
return;
}
@@ -84,7 +97,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
if (!(file = fopen(fileName2->getCString(), "rb"))) {
fileName2->upperCase();
if (!(file = fopen(fileName2->getCString(), "rb"))) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
+ error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
delete fileName2;
errCode = errOpenFile;
return;
@@ -103,16 +116,15 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
#ifdef WIN32
PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
+ GString *userPassword, PDFCore *coreA) {
OSVERSIONINFO version;
- wchar_t fileName2[_MAX_PATH + 1];
Object obj;
int i;
ok = gFalse;
errCode = errNone;
- guiData = guiDataA;
+ core = coreA;
file = NULL;
str = NULL;
@@ -121,30 +133,28 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
+ optContent = NULL;
- //~ file name should be stored in Unicode (?)
+ // save both Unicode and 8-bit copies of the file name
fileName = new GString();
+ fileNameU = (wchar_t *)gmallocn(fileNameLen + 1, sizeof(wchar_t));
for (i = 0; i < fileNameLen; ++i) {
fileName->append((char)fileNameA[i]);
+ fileNameU[i] = fileNameA[i];
}
-
- // zero-terminate the file name string
- for (i = 0; i < fileNameLen && i < _MAX_PATH; ++i) {
- fileName2[i] = fileNameA[i];
- }
- fileName2[i] = 0;
+ fileNameU[fileNameLen] = L'\0';
// try to open file
// NB: _wfopen is only available in NT
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- file = _wfopen(fileName2, L"rb");
+ file = _wfopen(fileNameU, L"rb");
} else {
file = fopen(fileName->getCString(), "rb");
}
if (!file) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
+ error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
errCode = errOpenFile;
return;
}
@@ -158,14 +168,29 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
#endif
PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
+ GString *userPassword, PDFCore *coreA) {
+#ifdef WIN32
+ int n, i;
+#endif
+
ok = gFalse;
errCode = errNone;
- guiData = guiDataA;
+ core = coreA;
if (strA->getFileName()) {
fileName = strA->getFileName()->copy();
+#ifdef WIN32
+ n = fileName->getLength();
+ fileNameU = (wchar_t *)gmallocn(n + 1, sizeof(wchar_t));
+ for (i = 0; i < n; ++i) {
+ fileNameU[i] = (wchar_t)(fileName->getChar(i) & 0xff);
+ }
+ fileNameU[n] = L'\0';
+#endif
} else {
fileName = NULL;
+#ifdef WIN32
+ fileNameU = NULL;
+#endif
}
file = NULL;
str = strA;
@@ -174,6 +199,7 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
+ optContent = NULL;
ok = setup(ownerPassword, userPassword);
}
@@ -183,38 +209,71 @@ GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
// check header
checkHeader();
+ // read the xref and catalog
+ if (!PDFDoc::setup2(ownerPassword, userPassword, gFalse)) {
+ if (errCode == errDamaged || errCode == errBadCatalog) {
+ // try repairing the xref table
+ error(errSyntaxWarning, -1,
+ "PDF file is damaged - attempting to reconstruct xref table...");
+ if (!PDFDoc::setup2(ownerPassword, userPassword, gTrue)) {
+ return gFalse;
+ }
+ } else {
+ return gFalse;
+ }
+ }
+
+#ifndef DISABLE_OUTLINE
+ // read outline
+ outline = new Outline(catalog->getOutline(), xref);
+#endif
+
+ // read the optional content info
+ optContent = new OptionalContent(this);
+
+ // done
+ return gTrue;
+}
+
+GBool PDFDoc::setup2(GString *ownerPassword, GString *userPassword,
+ GBool repairXRef) {
// read xref table
- xref = new XRef(str);
+ xref = new XRef(str, repairXRef);
if (!xref->isOk()) {
- error(-1, "Couldn't read xref table");
+ error(errSyntaxError, -1, "Couldn't read xref table");
errCode = xref->getErrorCode();
+ delete xref;
+ xref = NULL;
return gFalse;
}
// check for encryption
if (!checkEncryption(ownerPassword, userPassword)) {
errCode = errEncrypted;
+ delete xref;
+ xref = NULL;
return gFalse;
}
// read catalog
- catalog = new Catalog(xref);
+ catalog = new Catalog(this);
if (!catalog->isOk()) {
- error(-1, "Couldn't read page catalog");
+ error(errSyntaxError, -1, "Couldn't read page catalog");
errCode = errBadCatalog;
+ delete catalog;
+ catalog = NULL;
+ delete xref;
+ xref = NULL;
return gFalse;
}
-#ifndef DISABLE_OUTLINE
- // read outline
- outline = new Outline(catalog->getOutline(), xref);
-#endif
-
- // done
return gTrue;
}
PDFDoc::~PDFDoc() {
+ if (optContent) {
+ delete optContent;
+ }
#ifndef DISABLE_OUTLINE
if (outline) {
delete outline;
@@ -235,6 +294,11 @@ PDFDoc::~PDFDoc() {
if (fileName) {
delete fileName;
}
+#ifdef WIN32
+ if (fileNameU) {
+ gfree(fileNameU);
+ }
+#endif
}
// Check for a PDF header on this stream. Skip past some garbage
@@ -255,19 +319,20 @@ void PDFDoc::checkHeader() {
}
}
if (i >= headerSearchSize - 5) {
- error(-1, "May not be a PDF file (continuing anyway)");
+ error(errSyntaxWarning, -1, "May not be a PDF file (continuing anyway)");
return;
}
str->moveStart(i);
if (!(p = strtok(&hdrBuf[i+5], " \t\n\r"))) {
- error(-1, "May not be a PDF file (continuing anyway)");
+ error(errSyntaxWarning, -1, "May not be a PDF file (continuing anyway)");
return;
}
pdfVersion = atof(p);
if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
pdfVersion > supportedPDFVersionNum + 0.0001) {
- error(-1, "PDF version %s -- xpdf supports version %s"
- " (continuing anyway)", p, supportedPDFVersionStr);
+ error(errSyntaxWarning, -1,
+ "PDF version {0:s} -- xpdf supports version {1:s} (continuing anyway)",
+ p, supportedPDFVersionStr);
}
}
@@ -280,7 +345,10 @@ GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) {
xref->getTrailerDict()->dictLookup("Encrypt", &encrypt);
if ((encrypted = encrypt.isDict())) {
if ((secHdlr = SecurityHandler::make(this, &encrypt))) {
- if (secHdlr->checkEncryption(ownerPassword, userPassword)) {
+ if (secHdlr->isUnencrypted()) {
+ // no encryption
+ ret = gTrue;
+ } else if (secHdlr->checkEncryption(ownerPassword, userPassword)) {
// authorization succeeded
xref->setEncryption(secHdlr->getPermissionFlags(),
secHdlr->getOwnerPasswordOk(),
@@ -315,7 +383,7 @@ void PDFDoc::displayPage(OutputDev *out, int page,
printf("***** page %d *****\n", page);
}
catalog->getPage(page)->display(out, hDPI, vDPI,
- rotate, useMediaBox, crop, printing, catalog,
+ rotate, useMediaBox, crop, printing,
abortCheckCbk, abortCheckCbkData);
}
@@ -329,6 +397,7 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
for (page = firstPage; page <= lastPage; ++page) {
displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing,
abortCheckCbk, abortCheckCbkData);
+ catalog->doneWithPage(page);
}
}
@@ -341,16 +410,16 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page,
catalog->getPage(page)->displaySlice(out, hDPI, vDPI,
rotate, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
- printing, catalog,
+ printing,
abortCheckCbk, abortCheckCbkData);
}
Links *PDFDoc::getLinks(int page) {
- return catalog->getPage(page)->getLinks(catalog);
+ return catalog->getPage(page)->getLinks();
}
void PDFDoc::processLinks(OutputDev *out, int page) {
- catalog->getPage(page)->processLinks(out, catalog);
+ catalog->getPage(page)->processLinks(out);
}
GBool PDFDoc::isLinearized() {
@@ -389,7 +458,7 @@ GBool PDFDoc::saveAs(GString *name) {
int c;
if (!(f = fopen(name->getCString(), "wb"))) {
- error(-1, "Couldn't open file '%s'", name->getCString());
+ error(errIO, -1, "Couldn't open file '{0:t}'", name);
return gFalse;
}
str->reset();
@@ -400,3 +469,90 @@ GBool PDFDoc::saveAs(GString *name) {
fclose(f);
return gTrue;
}
+
+GBool PDFDoc::saveEmbeddedFile(int idx, char *path) {
+ FILE *f;
+ GBool ret;
+
+ if (!(f = fopen(path, "wb"))) {
+ return gFalse;
+ }
+ ret = saveEmbeddedFile2(idx, f);
+ fclose(f);
+ return ret;
+}
+
+#ifdef WIN32
+GBool PDFDoc::saveEmbeddedFile(int idx, wchar_t *path, int pathLen) {
+ FILE *f;
+ OSVERSIONINFO version;
+ wchar_t path2w[_MAX_PATH + 1];
+ char path2c[_MAX_PATH + 1];
+ int i;
+ GBool ret;
+
+ // NB: _wfopen is only available in NT
+ version.dwOSVersionInfoSize = sizeof(version);
+ GetVersionEx(&version);
+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ for (i = 0; i < pathLen && i < _MAX_PATH; ++i) {
+ path2w[i] = path[i];
+ }
+ path2w[i] = 0;
+ f = _wfopen(path2w, L"wb");
+ } else {
+ for (i = 0; i < pathLen && i < _MAX_PATH; ++i) {
+ path2c[i] = (char)path[i];
+ }
+ path2c[i] = 0;
+ f = fopen(path2c, "wb");
+ }
+ if (!f) {
+ return gFalse;
+ }
+ ret = saveEmbeddedFile2(idx, f);
+ fclose(f);
+ return ret;
+}
+#endif
+
+GBool PDFDoc::saveEmbeddedFile2(int idx, FILE *f) {
+ Object strObj;
+ int c;
+
+ if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) {
+ return gFalse;
+ }
+ strObj.streamReset();
+ while ((c = strObj.streamGetChar()) != EOF) {
+ fputc(c, f);
+ }
+ strObj.streamClose();
+ strObj.free();
+ return gTrue;
+}
+
+char *PDFDoc::getEmbeddedFileMem(int idx, int *size) {
+ Object strObj;
+ char *buf;
+ int bufSize, len, c;
+
+ if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) {
+ return NULL;
+ }
+ strObj.streamReset();
+ bufSize = 1024;
+ buf = (char *)gmalloc(bufSize);
+ len = 0;
+ while ((c = strObj.streamGetChar()) != EOF) {
+ if (len == bufSize) {
+ bufSize *= 2;
+ buf = (char *)grealloc(buf, bufSize);
+ }
+ buf[len++] = (char)c;
+ }
+ strObj.streamClose();
+ strObj.free();
+ *size = len;
+ return buf;
+}
diff --git a/xpdf/PDFDoc.h b/xpdf/PDFDoc.h
index 208b61e..94fcfb7 100644
--- a/xpdf/PDFDoc.h
+++ b/xpdf/PDFDoc.h
@@ -27,6 +27,8 @@ class Links;
class LinkAction;
class LinkDest;
class Outline;
+class OptionalContent;
+class PDFCore;
//------------------------------------------------------------------------
// PDFDoc
@@ -36,13 +38,13 @@ class PDFDoc {
public:
PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
+ GString *userPassword = NULL, PDFCore *coreA = NULL);
#ifdef WIN32
PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
+ GString *userPassword = NULL, PDFCore *coreA = NULL);
#endif
PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
+ GString *userPassword = NULL, PDFCore *coreA = NULL);
~PDFDoc();
// Was PDF document successfully opened?
@@ -53,6 +55,9 @@ public:
// Get file name.
GString *getFileName() { return fileName; }
+#ifdef WIN32
+ wchar_t *getFileNameU() { return fileNameU; }
+#endif
// Get the xref table.
XRef *getXRef() { return xref; }
@@ -128,6 +133,9 @@ public:
Outline *getOutline() { return outline; }
#endif
+ // Return the OptionalContent object.
+ OptionalContent *getOptionalContent() { return optContent; }
+
// Is the file encrypted?
GBool isEncrypted() { return xref->isEncrypted(); }
@@ -154,27 +162,44 @@ public:
// Save this file with another name.
GBool saveAs(GString *name);
- // Return a pointer to the GUI (XPDFCore or WinPDFCore object).
- void *getGUIData() { return guiData; }
+ // Return a pointer to the PDFCore object.
+ PDFCore *getCore() { return core; }
+ // Get the list of embedded files.
+ int getNumEmbeddedFiles() { return catalog->getNumEmbeddedFiles(); }
+ Unicode *getEmbeddedFileName(int idx)
+ { return catalog->getEmbeddedFileName(idx); }
+ int getEmbeddedFileNameLength(int idx)
+ { return catalog->getEmbeddedFileNameLength(idx); }
+ GBool saveEmbeddedFile(int idx, char *path);
+#ifdef WIN32
+ GBool saveEmbeddedFile(int idx, wchar_t *path, int pathLen);
+#endif
+ char *getEmbeddedFileMem(int idx, int *size);
private:
GBool setup(GString *ownerPassword, GString *userPassword);
+ GBool setup2(GString *ownerPassword, GString *userPassword,
+ GBool repairXRef);
void checkHeader();
GBool checkEncryption(GString *ownerPassword, GString *userPassword);
+ GBool saveEmbeddedFile2(int idx, FILE *f);
GString *fileName;
+#ifdef WIN32
+ wchar_t *fileNameU;
+#endif
FILE *file;
BaseStream *str;
- void *guiData;
+ PDFCore *core;
double pdfVersion;
XRef *xref;
Catalog *catalog;
#ifndef DISABLE_OUTLINE
Outline *outline;
#endif
-
+ OptionalContent *optContent;
GBool ok;
int errCode;
diff --git a/xpdf/PDFDocEncoding.cc b/xpdf/PDFDocEncoding.cc
index 89dc382..d173cef 100644
--- a/xpdf/PDFDocEncoding.cc
+++ b/xpdf/PDFDocEncoding.cc
@@ -9,9 +9,9 @@
#include "PDFDocEncoding.h"
Unicode pdfDocEncoding[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, // 00
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, // 10
0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
diff --git a/xpdf/PSOutputDev.cc b/xpdf/PSOutputDev.cc
index 8a1a9e9..55e576b 100644
--- a/xpdf/PSOutputDev.cc
+++ b/xpdf/PSOutputDev.cc
@@ -19,6 +19,7 @@
#include <math.h>
#include "GString.h"
#include "GList.h"
+#include "GHash.h"
#include "config.h"
#include "GlobalParams.h"
#include "Object.h"
@@ -34,8 +35,10 @@
#include "Page.h"
#include "Stream.h"
#include "Annot.h"
+#include "PDFDoc.h"
#include "XRef.h"
#include "PreScanOutputDev.h"
+#include "CharCodeToUnicode.h"
#if HAVE_SPLASH
# include "Splash.h"
# include "SplashBitmap.h"
@@ -55,8 +58,8 @@
//------------------------------------------------------------------------
-// Resolution at which pages with transparency will be rasterized.
-#define splashDPI 300
+// Max size of a slice when rasterizing pages, in pixels.
+#define rasterizationSliceSize 20000000
//------------------------------------------------------------------------
// PostScript prolog and setup
@@ -69,7 +72,7 @@
// ^ ^----- s=psLevel*Sep, n=psLevel*
// +----- 1=psLevel1*, 2=psLevel2*, 3=psLevel3*
-static char *prolog[] = {
+static const char *prolog[] = {
"/xpdf 75 dict def xpdf begin",
"% PDF special state",
"/pdfDictSize 15 def",
@@ -82,16 +85,24 @@ static char *prolog[] = {
" } for",
"~123sn",
"/pdfSetup {",
- " 3 1 roll 2 array astore",
" /setpagedevice where {",
- " pop 3 dict begin",
+ " pop 2 dict begin",
+ " /Policies 1 dict dup begin /PageSize 6 def end def",
+ " { /Duplex true def } if",
+ " currentdict end setpagedevice",
+ " } {",
+ " pop",
+ " } ifelse",
+ "} def",
+ "/pdfSetupPaper {",
+ " 2 array astore",
+ " /setpagedevice where {",
+ " pop 2 dict begin",
" /PageSize exch def",
" /ImagingBBox null def",
- " /Policies 1 dict dup begin /PageSize 3 def end def",
- " { /Duplex true def } if",
" currentdict end setpagedevice",
" } {",
- " pop pop",
+ " pop",
" } ifelse",
"} def",
"~1sn",
@@ -377,82 +388,82 @@ static char *prolog[] = {
"/Td { pdfTextMat transform moveto } def",
"/Tm { /pdfTextMat exch def } def",
"% text string operators",
+ "/xyshow where {",
+ " pop",
+ " /xyshow2 {",
+ " dup length array",
+ " 0 2 2 index length 1 sub {",
+ " 2 index 1 index 2 copy get 3 1 roll 1 add get",
+ " pdfTextMat dtransform",
+ " 4 2 roll 2 copy 6 5 roll put 1 add 3 1 roll dup 4 2 roll put",
+ " } for",
+ " exch pop",
+ " xyshow",
+ " } def",
+ "}{",
+ " /xyshow2 {",
+ " currentfont /FontType get 0 eq {",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval show moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } {",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval show moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } ifelse",
+ " pop pop",
+ " } def",
+ "} ifelse",
"/cshow where {",
" pop",
- " /cshow2 {",
- " dup {",
- " pop pop",
- " 1 string dup 0 3 index put 3 index exec",
+ " /xycp {", // xycharpath
+ " 0 3 2 roll",
+ " {",
+ " pop pop currentpoint 3 2 roll",
+ " 1 string dup 0 4 3 roll put false charpath moveto",
+ " 2 copy get 2 index 2 index 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " 2 add",
" } exch cshow",
" pop pop",
" } def",
"}{",
- " /cshow2 {",
+ " /xycp {", // xycharpath
" currentfont /FontType get 0 eq {",
- " 0 2 2 index length 1 sub {",
- " 2 copy get exch 1 add 2 index exch get",
- " 2 copy exch 256 mul add",
- " 2 string dup 0 6 5 roll put dup 1 5 4 roll put",
- " 3 index exec",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval false charpath moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
" } for",
" } {",
- " dup {",
- " 1 string dup 0 3 index put 3 index exec",
- " } forall",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval false charpath moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
" } ifelse",
" pop pop",
" } def",
"} ifelse",
- "/awcp {", // awidthcharpath
- " exch {",
- " false charpath",
- " 5 index 5 index rmoveto",
- " 6 index eq { 7 index 7 index rmoveto } if",
- " } exch cshow2",
- " 6 {pop} repeat",
- "} def",
"/Tj {",
" fCol", // because stringwidth has to draw Type 3 chars
- " 1 index stringwidth pdfTextMat idtransform pop",
- " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
- " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj16 {",
- " fCol", // because stringwidth has to draw Type 3 chars
- " 2 index stringwidth pdfTextMat idtransform pop",
- " sub exch div",
- " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj16V {",
- " fCol", // because stringwidth has to draw Type 3 chars
- " 2 index stringwidth pdfTextMat idtransform exch pop",
- " sub exch div",
- " 0 pdfWordSpacing pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing add 0 exch",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj1 {",
" 0 pdfTextRise pdfTextMat dtransform rmoveto",
- " currentpoint 8 2 roll",
+ " currentpoint 4 2 roll",
" pdfTextRender 1 and 0 eq {",
- " 6 copy awidthshow",
+ " 2 copy xyshow2",
" } if",
" pdfTextRender 3 and dup 1 eq exch 2 eq or {",
- " 7 index 7 index moveto",
- " 6 copy",
+ " 3 index 3 index moveto",
+ " 2 copy",
" currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
- " false awcp currentpoint stroke moveto",
+ " xycp currentpoint stroke moveto",
" } if",
" pdfTextRender 4 and 0 ne {",
- " 8 6 roll moveto",
- " false awcp",
+ " 4 2 roll moveto xycp",
" /pdfTextClipPath [ pdfTextClipPath aload pop",
" {/moveto cvx}",
" {/lineto cvx}",
@@ -461,13 +472,13 @@ static char *prolog[] = {
" pathforall ] def",
" currentpoint newpath moveto",
" } {",
- " 8 {pop} repeat",
+ " pop pop pop pop",
" } ifelse",
" 0 pdfTextRise neg pdfTextMat dtransform rmoveto",
"} def",
- "/TJm { pdfFontSize 0.001 mul mul neg 0",
+ "/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0",
" pdfTextMat dtransform rmoveto } def",
- "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
+ "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch",
" pdfTextMat dtransform rmoveto } def",
"/Tclip { pdfTextClipPath cvx exec clip newpath",
" /pdfTextClipPath [] def } def",
@@ -495,19 +506,52 @@ static char *prolog[] = {
" fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
" { currentfile pdfImBuf1 readhexstring pop } imagemask",
"} def",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
"/pdfImM1a {",
- " { 2 copy get exch 1 add exch } imagemask",
+ " { pdfImStr } imagemask",
" pop pop",
"} def",
"~23sn",
- "% Level 2 image operators",
+ "% Level 2/3 image operators",
"/pdfImBuf 100 string def",
- "/pdfIm {",
- " image",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
+ "/skipEOD {",
" { currentfile pdfImBuf readline",
" not { pop exit } if",
" (%-EOD-) eq { exit } if } loop",
"} def",
+ "/pdfIm { image skipEOD } def",
+ "~3sn",
+ "/pdfMask {",
+ " /ReusableStreamDecode filter",
+ " skipEOD",
+ " /maskStream exch def",
+ "} def",
+ "/pdfMaskEnd { maskStream closefile } def",
+ "/pdfMaskInit {",
+ " /maskArray exch def",
+ " /maskIdx 0 def",
+ "} def",
+ "/pdfMaskSrc {",
+ " maskIdx maskArray length lt {",
+ " maskArray maskIdx get",
+ " /maskIdx maskIdx 1 add def",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
"~23s",
"/pdfImSep {",
" findcmykcustomcolor exch",
@@ -523,17 +567,10 @@ static char *prolog[] = {
" 255 exch sub put",
" } for }",
" 6 5 roll customcolorimage",
- " { currentfile pdfImBuf readline",
- " not { pop exit } if",
- " (%-EOD-) eq { exit } if } loop",
+ " skipEOD",
"} def",
"~23sn",
- "/pdfImM {",
- " fCol imagemask",
- " { currentfile pdfImBuf readline",
- " not { pop exit } if",
- " (%-EOD-) eq { exit } if } loop",
- "} def",
+ "/pdfImM { fCol imagemask skipEOD } def",
"/pr { 2 index 2 index 3 2 roll putinterval 4 add } def",
"/pdfImClip {",
" gsave",
@@ -607,7 +644,7 @@ static char *prolog[] = {
" func n array astore",
"} def",
"/axialSH {",
- " dup 0 eq {",
+ " dup 2 lt {",
" true",
" } {",
" dup 8 eq {",
@@ -699,7 +736,7 @@ static char *prolog[] = {
NULL
};
-static char *cmapProlog[] = {
+static const char *cmapProlog[] = {
"/CIDInit /ProcSet findresource begin",
"10 dict begin",
" begincmap",
@@ -749,29 +786,16 @@ static char *cmapProlog[] = {
//------------------------------------------------------------------------
struct PSSubstFont {
- char *psName; // PostScript name
+ const char *psName; // PostScript name
double mWidth; // width of 'm' character
};
-static char *psFonts[] = {
- "Courier",
- "Courier-Bold",
- "Courier-Oblique",
- "Courier-BoldOblique",
- "Helvetica",
- "Helvetica-Bold",
- "Helvetica-Oblique",
- "Helvetica-BoldOblique",
- "Symbol",
- "Times-Roman",
- "Times-Bold",
- "Times-Italic",
- "Times-BoldItalic",
- "ZapfDingbats",
- NULL
-};
-
-static PSSubstFont psSubstFonts[] = {
+// NB: must be in same order as base14SubstFonts in GfxFont.cc
+static PSSubstFont psBase14SubstFonts[14] = {
+ {"Courier", 0.600},
+ {"Courier-Oblique", 0.600},
+ {"Courier-Bold", 0.600},
+ {"Courier-BoldOblique", 0.600},
{"Helvetica", 0.833},
{"Helvetica-Oblique", 0.833},
{"Helvetica-Bold", 0.889},
@@ -780,22 +804,28 @@ static PSSubstFont psSubstFonts[] = {
{"Times-Italic", 0.722},
{"Times-Bold", 0.833},
{"Times-BoldItalic", 0.778},
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600}
+ // the last two are never used for substitution
+ {"Symbol", 0},
+ {"ZapfDingbats", 0}
+};
+
+// Mapping from Type 1/1C font file to PS font name.
+struct PST1FontName {
+ Ref fontFileID;
+ GString *psName; // PostScript font name used for this
+ // embedded font file
};
// Info for 8-bit fonts
struct PSFont8Info {
Ref fontID;
- Gushort *codeToGID; // code-to-GID mapping for TrueType fonts
+ int *codeToGID; // code-to-GID mapping for TrueType fonts
};
// Encoding info for substitute 16-bit font
struct PSFont16Enc {
Ref fontID;
- GString *enc;
+ GString *enc; // NULL means font wasn't correctly substituted
};
//------------------------------------------------------------------------
@@ -845,6 +875,13 @@ struct PSOutImgClipRect {
};
//------------------------------------------------------------------------
+
+struct PSOutPaperSize {
+ PSOutPaperSize(int wA, int hA) { w = wA; h = hA; }
+ int w, h;
+};
+
+//------------------------------------------------------------------------
// DeviceNRecoder
//------------------------------------------------------------------------
@@ -897,6 +934,9 @@ DeviceNRecoder::~DeviceNRecoder() {
if (imgStr) {
delete imgStr;
}
+ if (str->isEncoder()) {
+ delete str;
+ }
}
void DeviceNRecoder::reset() {
@@ -938,14 +978,16 @@ extern "C" {
typedef void (*SignalFunc)(int);
}
-static void outputToFile(void *stream, char *data, int len) {
+static void outputToFile(void *stream, const char *data, int len) {
fwrite(data, 1, len, (FILE *)stream);
}
-PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
+PSOutputDev::PSOutputDev(char *fileName, PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- GBool manualCtrlA) {
+ GBool manualCtrlA,
+ PSOutCustomCodeCbk customCodeCbkA,
+ void *customCodeCbkDataA) {
FILE *f;
PSFileType fileTypeA;
@@ -953,15 +995,18 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
underlayCbkData = NULL;
overlayCbk = NULL;
overlayCbkData = NULL;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
fontIDs = NULL;
- fontFileIDs = NULL;
- fontFileNames = NULL;
+ fontNames = new GHash(gTrue);
+ t1FontNames = NULL;
font8Info = NULL;
font16Enc = NULL;
imgIDs = NULL;
formIDs = NULL;
xobjStack = NULL;
+ paperSizes = NULL;
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
@@ -978,71 +1023,82 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
signal(SIGPIPE, (SignalFunc)SIG_IGN);
#endif
if (!(f = popen(fileName + 1, "w"))) {
- error(-1, "Couldn't run print command '%s'", fileName);
+ error(errIO, -1, "Couldn't run print command '{0:s}'", fileName);
ok = gFalse;
return;
}
#else
- error(-1, "Print commands are not supported ('%s')", fileName);
+ error(errIO, -1, "Print commands are not supported ('{0:s}')", fileName);
ok = gFalse;
return;
#endif
} else {
fileTypeA = psFile;
if (!(f = fopen(fileName, "w"))) {
- error(-1, "Couldn't open PostScript file '%s'", fileName);
+ error(errIO, -1, "Couldn't open PostScript file '{0:s}'", fileName);
ok = gFalse;
return;
}
}
init(outputToFile, f, fileTypeA,
- xrefA, catalog, firstPage, lastPage, modeA,
+ docA, firstPage, lastPage, modeA,
imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
}
PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
- XRef *xrefA, Catalog *catalog,
+ PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- GBool manualCtrlA) {
+ GBool manualCtrlA,
+ PSOutCustomCodeCbk customCodeCbkA,
+ void *customCodeCbkDataA) {
underlayCbk = NULL;
underlayCbkData = NULL;
overlayCbk = NULL;
overlayCbkData = NULL;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
fontIDs = NULL;
- fontFileIDs = NULL;
- fontFileNames = NULL;
+ fontNames = new GHash(gTrue);
+ t1FontNames = NULL;
font8Info = NULL;
font16Enc = NULL;
imgIDs = NULL;
formIDs = NULL;
xobjStack = NULL;
+ paperSizes = NULL;
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
t3String = NULL;
init(outputFuncA, outputStreamA, psGeneric,
- xrefA, catalog, firstPage, lastPage, modeA,
+ docA, firstPage, lastPage, modeA,
imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
}
void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
- PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ PSFileType fileTypeA, PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA) {
+ Catalog *catalog;
Page *page;
PDFRectangle *box;
+ PSOutPaperSize *size;
+ GList *names;
+ int pg, w, h, i;
// initialize
ok = gTrue;
outputFunc = outputFuncA;
outputStream = outputStreamA;
fileType = fileTypeA;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
+ catalog = doc->getCatalog();
level = globalParams->getPSLevel();
mode = modeA;
paperWidth = globalParams->getPSPaperWidth();
@@ -1055,18 +1111,34 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY);
}
if (paperWidth < 0 || paperHeight < 0) {
- // this check is needed in case the document has zero pages
- if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
- page = catalog->getPage(firstPage);
- paperWidth = (int)ceil(page->getMediaWidth());
- paperHeight = (int)ceil(page->getMediaHeight());
- } else {
- paperWidth = 1;
- paperHeight = 1;
+ paperMatch = gTrue;
+ paperSizes = new GList();
+ paperWidth = paperHeight = 1; // in case the document has zero pages
+ for (pg = (firstPage >= 1) ? firstPage : 1;
+ pg <= lastPage && pg <= catalog->getNumPages();
+ ++pg) {
+ page = catalog->getPage(pg);
+ w = (int)ceil(page->getMediaWidth());
+ h = (int)ceil(page->getMediaHeight());
+ for (i = 0; i < paperSizes->getLength(); ++i) {
+ size = (PSOutPaperSize *)paperSizes->get(i);
+ if (size->w == w && size->h == h) {
+ break;
+ }
+ }
+ if (i == paperSizes->getLength()) {
+ paperSizes->append(new PSOutPaperSize(w, h));
+ }
+ if (w > paperWidth) {
+ paperWidth = w;
+ }
+ if (h > paperHeight) {
+ paperHeight = h;
+ }
}
- imgLLX = imgLLY = 0;
- imgURX = paperWidth;
- imgURY = paperHeight;
+ // NB: img{LLX,LLY,URX,URY} will be set by startPage()
+ } else {
+ paperMatch = gFalse;
}
preload = globalParams->getPSPreload();
manualCtrl = manualCtrlA;
@@ -1088,17 +1160,21 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
clipLLX0 = clipLLY0 = 0;
clipURX0 = clipURY0 = -1;
- // initialize fontIDs, fontFileIDs, and fontFileNames lists
+ // initialize fontIDs and fontNames lists
fontIDSize = 64;
fontIDLen = 0;
fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
- fontFileIDSize = 64;
- fontFileIDLen = 0;
- fontFileIDs = (Ref *)gmallocn(fontFileIDSize, sizeof(Ref));
- fontFileNameSize = 64;
- fontFileNameLen = 0;
- fontFileNames = (GString **)gmallocn(fontFileNameSize, sizeof(GString *));
- nextTrueTypeNum = 0;
+ for (i = 0; i < 14; ++i) {
+ fontNames->add(new GString(psBase14SubstFonts[i].psName), 1);
+ }
+ names = globalParams->getPSResidentFonts();
+ for (i = 0; i < names->getLength(); ++i) {
+ fontNames->add((GString *)names->get(i), 1);
+ }
+ delete names;
+ t1FontNameSize = 64;
+ t1FontNameLen = 0;
+ t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName));
font8InfoLen = 0;
font8InfoSize = 0;
font16EncLen = 0;
@@ -1173,20 +1249,21 @@ PSOutputDev::~PSOutputDev() {
}
#endif
}
+ if (paperSizes) {
+ deleteGList(paperSizes, PSOutPaperSize);
+ }
if (embFontList) {
delete embFontList;
}
if (fontIDs) {
gfree(fontIDs);
}
- if (fontFileIDs) {
- gfree(fontFileIDs);
- }
- if (fontFileNames) {
- for (i = 0; i < fontFileNameLen; ++i) {
- delete fontFileNames[i];
+ delete fontNames;
+ if (t1FontNames) {
+ for (i = 0; i < t1FontNameLen; ++i) {
+ delete t1FontNames[i].psName;
}
- gfree(fontFileNames);
+ gfree(t1FontNames);
}
if (font8Info) {
for (i = 0; i < font8InfoLen; ++i) {
@@ -1196,7 +1273,9 @@ PSOutputDev::~PSOutputDev() {
}
if (font16Enc) {
for (i = 0; i < font16EncLen; ++i) {
- delete font16Enc[i].enc;
+ if (font16Enc[i].enc) {
+ delete font16Enc[i].enc;
+ }
}
gfree(font16Enc);
}
@@ -1216,7 +1295,9 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
PDFRectangle *mediaBox, PDFRectangle *cropBox,
int pageRotate) {
Object info, obj1;
+ PSOutPaperSize *size;
double x1, y1, x2, y2;
+ int i;
switch (mode) {
case psModePS:
@@ -1230,7 +1311,7 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
break;
}
- writePSFmt("% Produced by xpdf/pdftops {0:s}\n", xpdfVersion);
+ writePSFmt("%XpdfVersion: {0:s}\n", xpdfVersion);
xref->getDocInfo(&info);
if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) {
writePS("%%Creator: ");
@@ -1254,14 +1335,24 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
switch (mode) {
case psModePS:
- writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n",
- paperWidth, paperHeight);
+ if (paperMatch) {
+ for (i = 0; i < paperSizes->getLength(); ++i) {
+ size = (PSOutPaperSize *)paperSizes->get(i);
+ writePSFmt("%%{0:s} {1:d}x{2:d} {1:d} {2:d} 0 () ()\n",
+ i==0 ? "DocumentMedia:" : "+", size->w, size->h);
+ }
+ } else {
+ writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n",
+ paperWidth, paperHeight);
+ }
writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight);
writePSFmt("%%Pages: {0:d}\n", lastPage - firstPage + 1);
writePS("%%EndComments\n");
- writePS("%%BeginDefaults\n");
- writePS("%%PageMedia: plain\n");
- writePS("%%EndDefaults\n");
+ if (!paperMatch) {
+ writePS("%%BeginDefaults\n");
+ writePS("%%PageMedia: plain\n");
+ writePS("%%EndDefaults\n");
+ }
break;
case psModeEPS:
epsX1 = cropBox->x1;
@@ -1283,7 +1374,7 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
(int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2));
if (floor(x1) != ceil(x1) || floor(y1) != ceil(y1) ||
floor(x2) != ceil(x2) || floor(y2) != ceil(y2)) {
- writePSFmt("%%HiResBoundingBox: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n",
+ writePSFmt("%%HiResBoundingBox: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n",
x1, y1, x2, y2);
}
writePS("%%EndComments\n");
@@ -1302,8 +1393,8 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
void PSOutputDev::writeXpdfProcset() {
GBool lev1, lev2, lev3, sep, nonSep;
- char **p;
- char *q;
+ const char **p;
+ const char *q;
writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", xpdfVersion);
writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright);
@@ -1343,7 +1434,9 @@ void PSOutputDev::writeDocSetup(Catalog *catalog,
Page *page;
Dict *resDict;
Annots *annots;
- Object obj1, obj2;
+ Object *acroForm;
+ Object obj1, obj2, obj3;
+ GString *s;
int pg, i;
if (mode == psModeForm) {
@@ -1357,7 +1450,7 @@ void PSOutputDev::writeDocSetup(Catalog *catalog,
if ((resDict = page->getResourceDict())) {
setupResources(resDict);
}
- annots = new Annots(xref, catalog, page->getAnnots(&obj1));
+ annots = new Annots(doc, page->getAnnots(&obj1));
obj1.free();
for (i = 0; i < annots->getNumAnnots(); ++i) {
if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
@@ -1371,11 +1464,31 @@ void PSOutputDev::writeDocSetup(Catalog *catalog,
}
delete annots;
}
+ if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) {
+ if (acroForm->dictLookup("DR", &obj1)->isDict()) {
+ setupResources(obj1.getDict());
+ }
+ obj1.free();
+ if (acroForm->dictLookup("Fields", &obj1)->isArray()) {
+ for (i = 0; i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isDict()) {
+ if (obj2.dictLookup("DR", &obj3)->isDict()) {
+ setupResources(obj3.getDict());
+ }
+ obj3.free();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ }
if (mode != psModeForm) {
if (mode != psModeEPS && !manualCtrl) {
- writePSFmt("{0:d} {1:d} {2:s} pdfSetup\n",
- paperWidth, paperHeight,
+ writePSFmt("{0:s} pdfSetup\n",
globalParams->getPSDuplex() ? "true" : "false");
+ if (!paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", paperWidth, paperHeight);
+ }
}
#if OPI_SUPPORT
if (globalParams->getPSOPI()) {
@@ -1383,6 +1496,13 @@ void PSOutputDev::writeDocSetup(Catalog *catalog,
}
#endif
}
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0,
+ customCodeCbkData))) {
+ writePS(s->getCString());
+ delete s;
+ }
+ }
}
void PSOutputDev::writePageTrailer() {
@@ -1405,7 +1525,7 @@ void PSOutputDev::writeTrailer() {
writePS("%%DocumentProcessColors:");
if (processColors & psProcessCyan) {
writePS(" Cyan");
- }
+ }
if (processColors & psProcessMagenta) {
writePS(" Magenta");
}
@@ -1418,13 +1538,16 @@ void PSOutputDev::writeTrailer() {
writePS("\n");
writePS("%%DocumentCustomColors:");
for (cc = customColors; cc; cc = cc->next) {
- writePSFmt(" ({0:s})", cc->name->getCString());
+ writePS(" ");
+ writePSString(cc->name);
}
writePS("\n");
writePS("%%CMYKCustomColor:\n");
for (cc = customColors; cc; cc = cc->next) {
- writePSFmt("%%+ {0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t})\n",
- cc->c, cc->m, cc->y, cc->k, cc->name);
+ writePSFmt("%%+ {0:.4g} {1:.4g} {2:.4g} {3:.4g} ",
+ cc->c, cc->m, cc->y, cc->k);
+ writePSString(cc->name);
+ writePS("\n");
}
}
}
@@ -1558,18 +1681,15 @@ void PSOutputDev::setupFonts(Dict *resDict) {
}
void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
- Ref fontFileID;
- GString *name;
- PSFontParam *fontParam;
+ GfxFontLoc *fontLoc;
GString *psName;
- char buf[16];
GBool subst;
+ char buf[16];
UnicodeMap *uMap;
char *charName;
double xs, ys;
int code;
double w1, w2;
- double *fm;
int i, j;
// check if font is already set up
@@ -1587,119 +1707,120 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
}
fontIDs[fontIDLen++] = *font->getID();
+ psName = NULL;
xs = ys = 1;
subst = gFalse;
- // check for resident 8-bit font
- if (font->getName() &&
- (fontParam = globalParams->getPSFont(font->getName()))) {
- psName = new GString(fontParam->psFontName->getCString());
-
- // check for embedded Type 1 font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1 &&
- font->getEmbeddedFontID(&fontFileID)) {
- psName = filterPSName(font->getEmbeddedFontName());
- setupEmbeddedType1Font(&fontFileID, psName);
-
- // check for embedded Type 1C font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1C &&
- font->getEmbeddedFontID(&fontFileID)) {
- // use the PDF font name because the embedded font name might
- // not include the subset prefix
- psName = filterPSName(font->getOrigName());
- setupEmbeddedType1CFont(font, &fontFileID, psName);
-
- // check for embedded OpenType - Type 1C font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1COT &&
- font->getEmbeddedFontID(&fontFileID)) {
- // use the PDF font name because the embedded font name might
- // not include the subset prefix
- psName = filterPSName(font->getOrigName());
- setupEmbeddedOpenTypeT1CFont(font, &fontFileID, psName);
-
- // check for external Type 1 font file
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1 &&
- font->getExtFontFile()) {
- // this assumes that the PS font name matches the PDF font name
- psName = font->getName()->copy();
- setupExternalType1Font(font->getExtFontFile(), psName);
-
- // check for embedded TrueType font
- } else if (globalParams->getPSEmbedTrueType() &&
- (font->getType() == fontTrueType ||
- font->getType() == fontTrueTypeOT) &&
- font->getEmbeddedFontID(&fontFileID)) {
- psName = filterPSName(font->getEmbeddedFontName());
- setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
-
- // check for external TrueType font file
- } else if (globalParams->getPSEmbedTrueType() &&
- font->getType() == fontTrueType &&
- font->getExtFontFile()) {
- psName = filterPSName(font->getName());
- setupExternalTrueTypeFont(font, psName);
-
- // check for embedded CID PostScript font
- } else if (globalParams->getPSEmbedCIDPostScript() &&
- font->getType() == fontCIDType0C &&
- font->getEmbeddedFontID(&fontFileID)) {
- psName = filterPSName(font->getEmbeddedFontName());
- setupEmbeddedCIDType0Font(font, &fontFileID, psName);
-
- // check for embedded CID TrueType font
- } else if (globalParams->getPSEmbedCIDTrueType() &&
- (font->getType() == fontCIDType2 ||
- font->getType() == fontCIDType2OT) &&
- font->getEmbeddedFontID(&fontFileID)) {
- psName = filterPSName(font->getEmbeddedFontName());
- //~ should check to see if font actually uses vertical mode
- setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue);
-
- // check for embedded OpenType - CID CFF font
- } else if (globalParams->getPSEmbedCIDPostScript() &&
- font->getType() == fontCIDType0COT &&
- font->getEmbeddedFontID(&fontFileID)) {
- psName = filterPSName(font->getEmbeddedFontName());
- setupEmbeddedOpenTypeCFFFont(font, &fontFileID, psName);
-
- // check for Type 3 font
- } else if (font->getType() == fontType3) {
+ if (font->getType() == fontType3) {
psName = GString::format("T3_{0:d}_{1:d}",
font->getID()->num, font->getID()->gen);
setupType3Font(font, psName, parentResDict);
-
- // do 8-bit font substitution
- } else if (!font->isCIDFont()) {
- subst = gTrue;
- name = font->getName();
- psName = NULL;
- if (name) {
- for (i = 0; psFonts[i]; ++i) {
- if (name->cmp(psFonts[i]) == 0) {
- psName = new GString(psFonts[i]);
- break;
+ } else {
+ fontLoc = font->locateFont(xref, gTrue);
+ switch (fontLoc->locType) {
+ case gfxFontLocEmbedded:
+ switch (fontLoc->fontType) {
+ case fontType1:
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getEmbeddedFontName()->copy();
+ setupEmbeddedType1Font(&fontLoc->embFontID, psName);
+ break;
+ case fontType1C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontType1COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType0C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, gTrue);
+ break;
+ case fontCIDType0COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName);
+ break;
+ default:
+ break;
+ }
+ break;
+ case gfxFontLocExternal:
+ //~ add cases for external 16-bit fonts
+ switch (fontLoc->fontType) {
+ case fontType1:
+ if (font->getName()) {
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getName()->copy();
+ } else {
+ //~ this won't work -- the PS font name won't match
+ psName = makePSFontName(font, font->getID());
}
+ setupExternalType1Font(fontLoc->path, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupExternalTrueTypeFont(font, fontLoc->path, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, gTrue);
+ break;
+ default:
+ break;
}
+ break;
+ case gfxFontLocResident:
+ psName = fontLoc->path->copy();
+ break;
}
+
if (!psName) {
- if (font->isFixedWidth()) {
- i = 8;
- } else if (font->isSerif()) {
- i = 4;
+ if (font->isCIDFont()) {
+ error(errSyntaxError, -1,
+ "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)",
+ font->getName() ? font->getName()->getCString()
+ : "(unnamed)",
+ ((GfxCIDFont *)font)->getCollection()
+ ? ((GfxCIDFont *)font)->getCollection()->getCString()
+ : "(unknown)");
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc,
+ font16EncSize,
+ sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ font16Enc[font16EncLen].enc = NULL;
+ ++font16EncLen;
} else {
- i = 0;
- }
- if (font->isBold()) {
- i += 2;
+ error(errSyntaxError, -1,
+ "Couldn't find a font to substitute for '{0:s}'",
+ font->getName() ? font->getName()->getCString()
+ : "(unnamed)");
}
- if (font->isItalic()) {
- i += 1;
- }
- psName = new GString(psSubstFonts[i].psName);
+ delete fontLoc;
+ return;
+ }
+
+ // scale substituted 8-bit fonts
+ if (fontLoc->locType == gfxFontLocResident &&
+ fontLoc->substIdx >= 0) {
+ subst = gTrue;
for (code = 0; code < 256; ++code) {
if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) &&
charName[0] == 'm' && charName[1] == '\0') {
@@ -1711,56 +1832,37 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
} else {
w1 = 0;
}
- w2 = psSubstFonts[i].mWidth;
+ w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth;
xs = w1 / w2;
if (xs < 0.1) {
xs = 1;
}
- if (font->getType() == fontType3) {
- // This is a hack which makes it possible to substitute for some
- // Type 3 fonts. The problem is that it's impossible to know what
- // the base coordinate system used in the font is without actually
- // rendering the font.
- ys = xs;
- fm = font->getFontMatrix();
- if (fm[0] != 0) {
- ys *= fm[3] / fm[0];
- }
+ }
+
+ // handle encodings for substituted CID fonts
+ if (fontLoc->locType == gfxFontLocResident &&
+ fontLoc->fontType >= fontCIDType0) {
+ subst = gTrue;
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc,
+ font16EncSize,
+ sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding))) {
+ font16Enc[font16EncLen].enc = fontLoc->encoding->copy();
+ uMap->decRefCnt();
} else {
- ys = 1;
- }
- }
-
- // do 16-bit font substitution
- } else if ((fontParam = globalParams->
- getPSFont16(font->getName(),
- ((GfxCIDFont *)font)->getCollection(),
- font->getWMode()))) {
- subst = gTrue;
- psName = fontParam->psFontName->copy();
- if (font16EncLen >= font16EncSize) {
- font16EncSize += 16;
- font16Enc = (PSFont16Enc *)greallocn(font16Enc,
- font16EncSize, sizeof(PSFont16Enc));
- }
- font16Enc[font16EncLen].fontID = *font->getID();
- font16Enc[font16EncLen].enc = fontParam->encoding->copy();
- if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) {
- uMap->decRefCnt();
+ error(errSyntaxError, -1,
+ "Couldn't find Unicode map for 16-bit font encoding '{0:t}'",
+ fontLoc->encoding);
+ font16Enc[font16EncLen].enc = NULL;
+ }
++font16EncLen;
- } else {
- error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'",
- font16Enc[font16EncLen].enc->getCString());
}
- // give up - can't do anything with this font
- } else {
- error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)",
- font->getName() ? font->getName()->getCString() : "(unnamed)",
- ((GfxCIDFont *)font)->getCollection()
- ? ((GfxCIDFont *)font)->getCollection()->getCString()
- : "(unknown)");
- return;
+ delete fontLoc;
}
// generate PostScript code to set up the font
@@ -1775,7 +1877,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
font->getWMode());
}
} else {
- writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.4g} {4:.4g}\n",
+ writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.6g} {4:.6g}\n",
font->getID()->num, font->getID()->gen, psName, xs, ys);
for (i = 0; i < 256; i += 8) {
writePS((char *)((i == 0) ? "[ " : " "));
@@ -1787,11 +1889,6 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
charName = buf;
} else {
charName = ((Gfx8BitFont *)font)->getCharName(i+j);
- // this is a kludge for broken PDF files that encode char 32
- // as .notdef
- if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
- charName = "space";
- }
}
writePS("/");
writePSName(charName ? charName : (char *)".notdef");
@@ -1821,36 +1918,30 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
- return;
- }
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (fontNames->lookupInt(psName)) {
+ return;
}
- fontFileIDs[fontFileIDLen++] = *id;
+ fontNames->add(psName->copy(), 1);
// get the font stream and info
refObj.initRef(id->num, id->gen);
refObj.fetch(xref, &strObj);
refObj.free();
if (!strObj.isStream()) {
- error(-1, "Embedded font file object is not a stream");
+ error(errSyntaxError, -1, "Embedded font file object is not a stream");
goto err1;
}
if (!(dict = strObj.streamGetDict())) {
- error(-1, "Embedded font stream is missing its dictionary");
+ error(errSyntaxError, -1,
+ "Embedded font stream is missing its dictionary");
goto err1;
}
dict->lookup("Length1", &obj1);
dict->lookup("Length2", &obj2);
dict->lookup("Length3", &obj3);
if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) {
- error(-1, "Missing length fields in embedded font stream dictionary");
+ error(errSyntaxError, -1,
+ "Missing length fields in embedded font stream dictionary");
obj1.free();
obj2.free();
obj3.free();
@@ -1880,7 +1971,8 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
for (i = 0; i < 4; ++i) {
start[i] = strObj.streamGetChar();
if (start[i] == EOF) {
- error(-1, "Unexpected end of file in embedded font stream");
+ error(errSyntaxError, -1,
+ "Unexpected end of file in embedded font stream");
goto err1;
}
if (!((start[i] >= '0' && start[i] <= '9') ||
@@ -1947,22 +2039,12 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) {
FILE *fontFile;
int c;
- int i;
// check if font is already embedded
- for (i = 0; i < fontFileNameLen; ++i) {
- if (!fontFileNames[i]->cmp(fileName)) {
- return;
- }
- }
-
- // add entry to fontFileNames list
- if (fontFileNameLen >= fontFileNameSize) {
- fontFileNameSize += 64;
- fontFileNames = (GString **)greallocn(fontFileNames,
- fontFileNameSize, sizeof(GString *));
+ if (fontNames->lookupInt(psName)) {
+ return;
}
- fontFileNames[fontFileNameLen++] = fileName->copy();
+ fontNames->add(psName->copy(), 1);
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -1972,7 +2054,7 @@ void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) {
// copy the font file
if (!(fontFile = fopen(fileName->getCString(), "rb"))) {
- error(-1, "Couldn't open external font file");
+ error(errIO, -1, "Couldn't open external font file");
return;
}
while ((c = fgetc(fontFile)) != EOF) {
@@ -1992,18 +2074,22 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2012,13 +2098,14 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 1 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- ffT1C->convertToType1(psName->getCString(), NULL, gTrue,
- outputFunc, outputStream);
- delete ffT1C;
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ ffT1C->convertToType1(psName->getCString(), NULL, gTrue,
+ outputFunc, outputStream);
+ delete ffT1C;
+ }
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2032,18 +2119,22 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2052,15 +2143,16 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 1 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- ffTT->convertToType1(psName->getCString(), NULL, gTrue,
- outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ ffTT->convertToType1(psName->getCString(), NULL, gTrue,
+ outputFunc, outputStream);
+ }
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2071,26 +2163,7 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
char *fontBuf;
int fontLen;
FoFiTrueType *ffTT;
- Gushort *codeToGID;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen) {
- psName->appendf("_{0:d}", nextTrueTypeNum++);
- break;
- }
- }
-
- // add entry to fontFileIDs list
- if (i == fontFileIDLen) {
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
- }
- fontFileIDs[fontFileIDLen++] = *id;
- }
+ int *codeToGID;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2099,60 +2172,38 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 42 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
- ffTT->convertToType42(psName->getCString(),
- ((Gfx8BitFont *)font)->getHasEncoding()
- ? ((Gfx8BitFont *)font)->getEncoding()
- : (char **)NULL,
- codeToGID, outputFunc, outputStream);
- if (codeToGID) {
- if (font8InfoLen >= font8InfoSize) {
- font8InfoSize += 16;
- font8Info = (PSFont8Info *)greallocn(font8Info,
- font8InfoSize,
- sizeof(PSFont8Info));
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getHasEncoding()
+ ? ((Gfx8BitFont *)font)->getEncoding()
+ : (char **)NULL,
+ codeToGID, outputFunc, outputStream);
+ if (codeToGID) {
+ if (font8InfoLen >= font8InfoSize) {
+ font8InfoSize += 16;
+ font8Info = (PSFont8Info *)greallocn(font8Info,
+ font8InfoSize,
+ sizeof(PSFont8Info));
+ }
+ font8Info[font8InfoLen].fontID = *font->getID();
+ font8Info[font8InfoLen].codeToGID = codeToGID;
+ ++font8InfoLen;
}
- font8Info[font8InfoLen].fontID = *font->getID();
- font8Info[font8InfoLen].codeToGID = codeToGID;
- ++font8InfoLen;
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
}
-void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
- GString *fileName;
- char *fontBuf;
- int fontLen;
+void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *fileName,
+ GString *psName) {
FoFiTrueType *ffTT;
- Gushort *codeToGID;
- int i;
-
- // check if font is already embedded
- fileName = font->getExtFontFile();
- for (i = 0; i < fontFileNameLen; ++i) {
- if (!fontFileNames[i]->cmp(fileName)) {
- psName->appendf("_{0:d}", nextTrueTypeNum++);
- break;
- }
- }
-
- // add entry to fontFileNames list
- if (i == fontFileNameLen) {
- if (fontFileNameLen >= fontFileNameSize) {
- fontFileNameSize += 64;
- fontFileNames =
- (GString **)greallocn(fontFileNames,
- fontFileNameSize, sizeof(GString *));
- }
- fontFileNames[fontFileNameLen++] = fileName->copy();
- }
+ int *codeToGID;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2161,8 +2212,7 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
embFontList->append("\n");
// convert it to a Type 42 font
- fontBuf = font->readExtFontFile(&fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if ((ffTT = FoFiTrueType::load(fileName->getCString()))) {
codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
ffTT->convertToType42(psName->getCString(),
((Gfx8BitFont *)font)->getHasEncoding()
@@ -2182,7 +2232,6 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
}
delete ffTT;
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2196,18 +2245,22 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2216,18 +2269,21 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffT1C->convertToCIDType0(psName->getCString(), NULL, 0,
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffT1C->convertToType0(psName->getCString(), NULL, 0,
+ outputFunc, outputStream);
+ }
+ delete ffT1C;
}
- delete ffT1C;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2239,23 +2295,50 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
char *fontBuf;
int fontLen;
FoFiTrueType *ffTT;
- int i;
- // check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen) {
- psName->appendf("_{0:d}", nextTrueTypeNum++);
- break;
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ }
+ delete ffTT;
}
+ gfree(fontBuf);
}
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
- }
- fontFileIDs[fontFileIDLen++] = *id;
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
+ GString *fileName,
+ GString *psName,
+ GBool needVerticalMetrics) {
+ FoFiTrueType *ffTT;
+ int *codeToGID;
+ int codeToGIDLen;
+ CharCodeToUnicode *ctu;
+ Unicode uBuf[8];
+ int cmap, code;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2264,26 +2347,62 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType2(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- outputFunc, outputStream);
+ //~ this should use fontNum to load the correct font
+ if ((ffTT = FoFiTrueType::load(fileName->getCString()))) {
+
+ // check for embedding permission
+ if (ffTT->getEmbeddingRights() >= 1) {
+
+ // create a CID-to-GID mapping, via Unicode
+ if ((ctu = ((GfxCIDFont *)font)->getToUnicode())) {
+ // look for a Unicode cmap
+ for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) {
+ if ((ffTT->getCmapPlatform(cmap) == 3 &&
+ ffTT->getCmapEncoding(cmap) == 1) ||
+ ffTT->getCmapPlatform(cmap) == 0) {
+ break;
+ }
+ }
+ if (cmap < ffTT->getNumCmaps()) {
+ // map CID -> Unicode -> GID
+ codeToGIDLen = ctu->getLength();
+ codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
+ for (code = 0; code < codeToGIDLen; ++code) {
+ if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
+ codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]);
+ } else {
+ codeToGID[code] = 0;
+ }
+ }
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->getCString(),
+ codeToGID, codeToGIDLen,
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
+ codeToGID, codeToGIDLen,
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ }
+ gfree(codeToGID);
+ }
+ ctu->decRefCnt();
+ } else {
+ error(errSyntaxError, -1,
+ "Couldn't find a mapping to Unicode for font '{0:s}'",
+ font->getName() ? font->getName()->getCString() : "(unnamed)");
+ }
} else {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- outputFunc, outputStream);
+ error(errSyntaxError, -1,
+ "TrueType font '%s' does not allow embedding",
+ font->getName() ? font->getName()->getCString() : "(unnamed)");
+
}
delete ffTT;
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2297,18 +2416,22 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2317,21 +2440,27 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType0(psName->getCString(),
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->getCString(), outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ }
}
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2367,10 +2496,10 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
writePS("8 dict begin\n");
writePS("/FontType 3 def\n");
m = font->getFontMatrix();
- writePSFmt("/FontMatrix [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] def\n",
+ writePSFmt("/FontMatrix [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n",
m[0], m[1], m[2], m[3], m[4], m[5]);
m = font->getFontBBox();
- writePSFmt("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n",
m[0], m[1], m[2], m[3]);
writePS("/Encoding 256 array def\n");
writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
@@ -2390,9 +2519,10 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
box.y1 = m[1];
box.x2 = m[2];
box.y2 = m[3];
- gfx = new Gfx(xref, this, resDict, &box, NULL);
+ gfx = new Gfx(doc, this, resDict, &box, NULL);
inType3Char = gTrue;
for (i = 0; i < charProcs->getLength(); ++i) {
+ t3FillColorOnly = gFalse;
t3Cacheable = gFalse;
t3NeedsRestore = gFalse;
writePS("/");
@@ -2402,10 +2532,10 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
charProc.free();
if (t3String) {
if (t3Cacheable) {
- buf = GString::format("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} setcachedevice\n",
+ buf = GString::format("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} setcachedevice\n",
t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
} else {
- buf = GString::format("{0:.4g} {1:.4g} setcharwidth\n", t3WX, t3WY);
+ buf = GString::format("{0:.6g} {1:.6g} setcharwidth\n", t3WX, t3WY);
}
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
delete buf;
@@ -2430,9 +2560,45 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
writePS("%%EndResource\n");
}
+// Make a unique PS font name, based on the names given in the PDF
+// font object, and an object ID (font file object for
+GString *PSOutputDev::makePSFontName(GfxFont *font, Ref *id) {
+ GString *psName, *s;
+
+ if ((s = font->getEmbeddedFontName())) {
+ psName = filterPSName(s);
+ if (!fontNames->lookupInt(psName)) {
+ fontNames->add(psName->copy(), 1);
+ return psName;
+ }
+ delete psName;
+ }
+ if ((s = font->getName())) {
+ psName = filterPSName(s);
+ if (!fontNames->lookupInt(psName)) {
+ fontNames->add(psName->copy(), 1);
+ return psName;
+ }
+ delete psName;
+ }
+ psName = GString::format("FF{0:d}_{1:d}", id->num, id->gen);
+ if ((s = font->getEmbeddedFontName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ } else if ((s = font->getName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ }
+ fontNames->add(psName->copy(), 1);
+ return psName;
+}
+
void PSOutputDev::setupImages(Dict *resDict) {
- Object xObjDict, xObj, xObjRef, subtypeObj;
- int i;
+ Object xObjDict, xObj, xObjRef, subtypeObj, maskObj, maskRef;
+ Ref imgID;
+ int i, j;
if (!(mode == psModeForm || inType3Char || preload)) {
return;
@@ -2447,9 +2613,32 @@ void PSOutputDev::setupImages(Dict *resDict) {
xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
if (subtypeObj.isName("Image")) {
if (xObjRef.isRef()) {
- setupImage(xObjRef.getRef(), xObj.getStream());
+ imgID = xObjRef.getRef();
+ for (j = 0; j < imgIDLen; ++j) {
+ if (imgIDs[j].num == imgID.num && imgIDs[j].gen == imgID.gen) {
+ break;
+ }
+ }
+ if (j == imgIDLen) {
+ if (imgIDLen >= imgIDSize) {
+ if (imgIDSize == 0) {
+ imgIDSize = 64;
+ } else {
+ imgIDSize *= 2;
+ }
+ imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
+ }
+ imgIDs[imgIDLen++] = imgID;
+ setupImage(imgID, xObj.getStream(), gFalse);
+ if (level >= psLevel3 &&
+ xObj.streamGetDict()->lookup("Mask", &maskObj)->isStream()) {
+ setupImage(imgID, maskObj.getStream(), gTrue);
+ }
+ maskObj.free();
+ }
} else {
- error(-1, "Image in resource dict is not an indirect reference");
+ error(errSyntaxError, -1,
+ "Image in resource dict is not an indirect reference");
}
}
subtypeObj.free();
@@ -2461,30 +2650,12 @@ void PSOutputDev::setupImages(Dict *resDict) {
xObjDict.free();
}
-void PSOutputDev::setupImage(Ref id, Stream *str) {
+void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) {
GBool useRLE, useCompressed, useASCIIHex;
GString *s;
int c;
int size, line, col, i;
- // check if image is already setup
- for (i = 0; i < imgIDLen; ++i) {
- if (imgIDs[i].num == id.num && imgIDs[i].gen == id.gen) {
- return;
- }
- }
-
- // add entry to imgIDs list
- if (imgIDLen >= imgIDSize) {
- if (imgIDSize == 0) {
- imgIDSize = 64;
- } else {
- imgIDSize *= 2;
- }
- imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
- }
- imgIDs[imgIDLen++] = id;
-
// filters
//~ this does not correctly handle the DeviceN color space
//~ -- need to use DeviceNRecoder
@@ -2493,17 +2664,21 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
useCompressed = gFalse;
useASCIIHex = gTrue;
} else {
- s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
- if (s) {
+ if (globalParams->getPSUncompressPreloadedImages()) {
useRLE = gFalse;
- useCompressed = gTrue;
- delete s;
- } else {
- useRLE = gTrue;
useCompressed = gFalse;
+ } else {
+ s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
+ if (s) {
+ useRLE = gFalse;
+ useCompressed = gTrue;
+ delete s;
+ } else {
+ useRLE = gTrue;
+ useCompressed = gFalse;
+ }
}
- useASCIIHex = level == psLevel1 || level == psLevel1Sep ||
- globalParams->getPSASCIIHex();
+ useASCIIHex = globalParams->getPSASCIIHex();
}
if (useCompressed) {
str = str->getUndecodedStream();
@@ -2552,8 +2727,8 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
if (useRLE) {
++size;
}
- writePSFmt("{0:d} array dup /ImData_{1:d}_{2:d} exch def\n",
- size, id.num, id.gen);
+ writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n",
+ size, mask ? "Mask" : "Im", id.num, id.gen);
str->close();
// write the data into the array
@@ -2626,7 +2801,8 @@ void PSOutputDev::setupForms(Dict *resDict) {
if (xObjRef.isRef()) {
setupForm(xObjRef.getRef(), &xObj);
} else {
- error(-1, "Form in resource dict is not an indirect reference");
+ error(errSyntaxError, -1,
+ "Form in resource dict is not an indirect reference");
}
}
subtypeObj.free();
@@ -2670,7 +2846,7 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) {
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
bboxObj.free();
- error(-1, "Bad form bounding box");
+ error(errSyntaxError, -1, "Bad form bounding box");
return;
}
for (i = 0; i < 4; ++i) {
@@ -2701,14 +2877,14 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) {
writePSFmt("/f_{0:d}_{1:d} {{\n", id.num, id.gen);
writePS("q\n");
- writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] cm\n",
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n",
m[0], m[1], m[2], m[3], m[4], m[5]);
box.x1 = bbox[0];
box.y1 = bbox[1];
box.x2 = bbox[2];
box.y2 = bbox[3];
- gfx = new Gfx(xref, this, resDict, &box, &box);
+ gfx = new Gfx(doc, this, resDict, &box, &box);
gfx->display(strObj);
delete gfx;
@@ -2722,12 +2898,14 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI,
int rotateA, GBool useMediaBox, GBool crop,
int sliceX, int sliceY,
int sliceW, int sliceH,
- GBool printing, Catalog *catalog,
+ GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
-#if HAVE_SPLASH
PreScanOutputDev *scan;
GBool rasterize;
+#if HAVE_SPLASH
+ GBool mono;
+ double dpi;
SplashOutputDev *splashOut;
SplashColor paperColor;
PDFRectangle box;
@@ -2737,210 +2915,249 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI,
Object obj;
Guchar *p;
Guchar col[4];
+ double hDPI2, vDPI2;
double m0, m1, m2, m3, m4, m5;
+ int nStripes, stripeH, stripeY;
int c, w, h, x, y, comp, i;
+#endif
- scan = new PreScanOutputDev();
- page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- printing, catalog, abortCheckCbk, abortCheckCbkData);
- rasterize = scan->usesTransparency();
- delete scan;
+ if (globalParams->getPSAlwaysRasterize()) {
+ rasterize = gTrue;
+ } else {
+ scan = new PreScanOutputDev();
+ page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
+ sliceX, sliceY, sliceW, sliceH,
+ printing, abortCheckCbk, abortCheckCbkData);
+ rasterize = scan->usesTransparency() || scan->usesPatternImageMask();
+ delete scan;
+ }
if (!rasterize) {
return gTrue;
}
- // rasterize the page
- if (level == psLevel1) {
+#if HAVE_SPLASH
+ // get the rasterization parameters
+ dpi = globalParams->getPSRasterResolution();
+ mono = globalParams->getPSRasterMono();
+
+ // start the PS page
+ page->makeBox(dpi, dpi, rotateA, useMediaBox, gFalse,
+ sliceX, sliceY, sliceW, sliceH, &box, &crop);
+ rotateA += page->getRotate();
+ if (rotateA >= 360) {
+ rotateA -= 360;
+ } else if (rotateA < 0) {
+ rotateA += 360;
+ }
+ state = new GfxState(dpi, dpi, &box, rotateA, gFalse);
+ startPage(page->getNum(), state);
+ delete state;
+
+ // set up the SplashOutputDev
+ if (mono || level == psLevel1) {
paperColor[0] = 0xff;
splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse,
- paperColor, gTrue, gFalse);
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
#if SPLASH_CMYK
} else if (level == psLevel1Sep) {
paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse,
- paperColor, gTrue, gFalse);
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
#endif
} else {
paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse,
- paperColor, gTrue, gFalse);
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
}
splashOut->startDoc(xref);
- page->displaySlice(splashOut, splashDPI, splashDPI, rotateA,
- useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- printing, catalog, abortCheckCbk, abortCheckCbkData);
- // start the PS page
- page->makeBox(splashDPI, splashDPI, rotateA, useMediaBox, gFalse,
- sliceX, sliceY, sliceW, sliceH, &box, &crop);
- rotateA += page->getRotate();
- if (rotateA >= 360) {
- rotateA -= 360;
- } else if (rotateA < 0) {
- rotateA += 360;
+ // break the page into stripes
+ hDPI2 = xScale * dpi;
+ vDPI2 = yScale * dpi;
+ if (sliceW < 0 || sliceH < 0) {
+ if (useMediaBox) {
+ box = *page->getMediaBox();
+ } else {
+ box = *page->getCropBox();
+ }
+ sliceX = sliceY = 0;
+ sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0);
+ sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0);
}
- state = new GfxState(splashDPI, splashDPI, &box, rotateA, gFalse);
- startPage(page->getNum(), state);
- delete state;
- switch (rotateA) {
- case 0:
- default: // this should never happen
+ nStripes = (int)ceil((double)(sliceW * sliceH) /
+ (double)rasterizationSliceSize);
+ stripeH = (sliceH + nStripes - 1) / nStripes;
+
+ // render the stripes
+ for (stripeY = sliceY; stripeY < sliceH; stripeY += stripeH) {
+
+ // rasterize a stripe
+ page->makeBox(hDPI2, vDPI2, 0, useMediaBox, gFalse,
+ sliceX, stripeY, sliceW, stripeH, &box, &crop);
m0 = box.x2 - box.x1;
m1 = 0;
m2 = 0;
m3 = box.y2 - box.y1;
m4 = box.x1;
m5 = box.y1;
- break;
- case 90:
- m0 = 0;
- m1 = box.y2 - box.y1;
- m2 = -(box.x2 - box.x1);
- m3 = 0;
- m4 = box.x2;
- m5 = box.y1;
- break;
- case 180:
- m0 = -(box.x2 - box.x1);
- m1 = 0;
- m2 = 0;
- m3 = -(box.y2 - box.y1);
- m4 = box.x2;
- m5 = box.y2;
- break;
- case 270:
- m0 = 0;
- m1 = -(box.y2 - box.y1);
- m2 = box.x2 - box.x1;
- m3 = 0;
- m4 = box.x1;
- m5 = box.y2;
- break;
- }
-
- //~ need to add the process colors
-
- // draw the rasterized image
- bitmap = splashOut->getBitmap();
- w = bitmap->getWidth();
- h = bitmap->getHeight();
- writePS("gsave\n");
- writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] concat\n",
- m0, m1, m2, m3, m4, m5);
- switch (level) {
- case psLevel1:
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n",
- w, h, w, -h, h);
- p = bitmap->getDataPtr();
- i = 0;
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- writePSFmt("{0:02x}", *p++);
- if (++i == 32) {
- writePSChar('\n');
- i = 0;
- }
- }
- }
- if (i != 0) {
- writePSChar('\n');
- }
- break;
- case psLevel1Sep:
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n",
- w, h, w, -h, h);
- p = bitmap->getDataPtr();
- i = 0;
- col[0] = col[1] = col[2] = col[3] = 0;
- for (y = 0; y < h; ++y) {
- for (comp = 0; comp < 4; ++comp) {
+ page->displaySlice(splashOut, hDPI2, vDPI2,
+ (360 - page->getRotate()) % 360, useMediaBox, crop,
+ sliceX, stripeY, sliceW, stripeH,
+ printing, abortCheckCbk, abortCheckCbkData);
+
+ // draw the rasterized image
+ bitmap = splashOut->getBitmap();
+ w = bitmap->getWidth();
+ h = bitmap->getHeight();
+ writePS("gsave\n");
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
+ m0, m1, m2, m3, m4, m5);
+ switch (level) {
+ case psLevel1:
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n",
+ w, h, w, -h, h);
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
+ for (y = 0; y < h; ++y) {
for (x = 0; x < w; ++x) {
- writePSFmt("{0:02x}", p[4*x + comp]);
- col[comp] |= p[4*x + comp];
+ writePSFmt("{0:02x}", *p++);
if (++i == 32) {
writePSChar('\n');
i = 0;
}
}
}
- p += bitmap->getRowSize();
- }
- if (i != 0) {
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ break;
+ case psLevel1Sep:
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n",
+ w, h, w, -h, h);
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
+ col[0] = col[1] = col[2] = col[3] = 0;
+ for (y = 0; y < h; ++y) {
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < w; ++x) {
+ writePSFmt("{0:02x}", p[4*x + comp]);
+ col[comp] |= p[4*x + comp];
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
+ }
+ }
+ p -= bitmap->getRowSize();
+ }
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ if (col[0]) {
+ processColors |= psProcessCyan;
+ }
+ if (col[1]) {
+ processColors |= psProcessMagenta;
+ }
+ if (col[2]) {
+ processColors |= psProcessYellow;
+ }
+ if (col[3]) {
+ processColors |= psProcessBlack;
+ }
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ case psLevel3:
+ case psLevel3Sep:
+ if (mono) {
+ writePS("/DeviceGray setcolorspace\n");
+ } else {
+ writePS("/DeviceRGB setcolorspace\n");
+ }
+ writePS("<<\n /ImageType 1\n");
+ writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
+ writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
+ writePS(" /BitsPerComponent 8\n");
+ if (mono) {
+ writePS(" /Decode [0 1]\n");
+ } else {
+ writePS(" /Decode [0 1 0 1 0 1]\n");
+ }
+ writePS(" /DataSource currentfile\n");
+ if (globalParams->getPSASCIIHex()) {
+ writePS(" /ASCIIHexDecode filter\n");
+ } else {
+ writePS(" /ASCII85Decode filter\n");
+ }
+ writePS(" /RunLengthDecode filter\n");
+ writePS(">>\n");
+ writePS("image\n");
+ obj.initNull();
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ str0 = new MemStream((char *)p, 0, w * h * (mono ? 1 : 3), &obj);
+ str = new RunLengthEncoder(str0);
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
+ delete str;
+ delete str0;
writePSChar('\n');
+ processColors |= mono ? psProcessBlack : psProcessCMYK;
+ break;
}
- if (col[0]) {
- processColors |= psProcessCyan;
- }
- if (col[1]) {
- processColors |= psProcessMagenta;
- }
- if (col[2]) {
- processColors |= psProcessYellow;
- }
- if (col[3]) {
- processColors |= psProcessBlack;
- }
- break;
- case psLevel2:
- case psLevel2Sep:
- case psLevel3:
- case psLevel3Sep:
- writePS("/DeviceRGB setcolorspace\n");
- writePS("<<\n /ImageType 1\n");
- writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
- writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
- writePS(" /BitsPerComponent 8\n");
- writePS(" /Decode [0 1 0 1 0 1]\n");
- writePS(" /DataSource currentfile\n");
- if (globalParams->getPSASCIIHex()) {
- writePS(" /ASCIIHexDecode filter\n");
- } else {
- writePS(" /ASCII85Decode filter\n");
- }
- writePS(" /RunLengthDecode filter\n");
- writePS(">>\n");
- writePS("image\n");
- obj.initNull();
- str0 = new MemStream((char *)bitmap->getDataPtr(), 0, w * h * 3, &obj);
- str = new RunLengthEncoder(str0);
- if (globalParams->getPSASCIIHex()) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- str->reset();
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- str->close();
- delete str;
- delete str0;
- processColors |= psProcessCMYK;
- break;
+ writePS("grestore\n");
}
+
delete splashOut;
- writePS("grestore\n");
// finish the PS page
endPage();
return gFalse;
-#else
+
+#else // HAVE_SPLASH
+
+ error(errSyntaxWarning, -1,
+ "PDF page uses transparency and PSOutputDev was built without"
+ " the Splash rasterizer - output may not be correct");
return gTrue;
-#endif
+#endif // HAVE_SPLASH
}
void PSOutputDev::startPage(int pageNum, GfxState *state) {
- int x1, y1, x2, y2, width, height;
+ Page *page;
+ int x1, y1, x2, y2, width, height, t;
int imgWidth, imgHeight, imgWidth2, imgHeight2;
GBool landscape;
-
+ GString *s;
if (mode == psModePS) {
writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage);
+ if (paperMatch) {
+ page = doc->getCatalog()->getPage(pageNum);
+ imgLLX = imgLLY = 0;
+ imgURX = (int)ceil(page->getMediaWidth());
+ imgURY = (int)ceil(page->getMediaHeight());
+ if (state->getRotate() == 90 || state->getRotate() == 270) {
+ t = imgURX;
+ imgURX = imgURY;
+ imgURY = t;
+ }
+ writePSFmt("%%PageMedia: {0:d}x{1:d}\n", imgURX, imgURY);
+ writePSFmt("%%PageBoundingBox: 0 0 {0:d} {1:d}\n", imgURX, imgURY);
+ }
writePS("%%BeginPageSetup\n");
}
@@ -2966,20 +3183,25 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
height = y2 - y1;
tx = ty = 0;
// rotation and portrait/landscape mode
- if (rotate0 >= 0) {
+ if (paperMatch) {
+ rotate = (360 - state->getRotate()) % 360;
+ landscape = gFalse;
+ } else if (rotate0 >= 0) {
rotate = (360 - rotate0) % 360;
landscape = gFalse;
} else {
rotate = (360 - state->getRotate()) % 360;
if (rotate == 0 || rotate == 180) {
- if (width > height && width > imgWidth) {
+ if ((width < height && imgWidth > imgHeight && height > imgHeight) ||
+ (width > height && imgWidth < imgHeight && width > imgWidth)) {
rotate += 90;
landscape = gTrue;
} else {
landscape = gFalse;
}
} else { // rotate == 90 || rotate == 270
- if (height > width && height > imgWidth) {
+ if ((height < width && imgWidth > imgHeight && width > imgHeight) ||
+ (height > width && imgWidth < imgHeight && height > imgWidth)) {
rotate = 270 - rotate;
landscape = gTrue;
} else {
@@ -2989,6 +3211,9 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
}
writePSFmt("%%PageOrientation: {0:s}\n",
landscape ? "Landscape" : "Portrait");
+ if (paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
+ }
writePS("pdfStartPage\n");
if (rotate == 0) {
imgWidth2 = imgWidth;
@@ -3015,9 +3240,9 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
xScale = xScale0;
yScale = yScale0;
} else if ((globalParams->getPSShrinkLarger() &&
- (width > imgWidth2 || height > imgHeight2)) ||
- (globalParams->getPSExpandSmaller() &&
- (width < imgWidth2 && height < imgHeight2))) {
+ (width > imgWidth2 || height > imgHeight2)) ||
+ (globalParams->getPSExpandSmaller() &&
+ (width < imgWidth2 && height < imgHeight2))) {
xScale = (double)imgWidth2 / (double)width;
yScale = (double)imgHeight2 / (double)height;
if (yScale < xScale) {
@@ -3038,8 +3263,8 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
}
// center
if (tx0 >= 0 && ty0 >= 0) {
- tx += rotate == 0 ? tx0 : ty0;
- ty += rotate == 0 ? ty0 : -tx0;
+ tx += (rotate == 0 || rotate == 180) ? tx0 : ty0;
+ ty += (rotate == 0 || rotate == 180) ? ty0 : -tx0;
} else if (globalParams->getPSCenter()) {
if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2;
@@ -3049,22 +3274,21 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
ty += (imgHeight2 - yScale * height) / 2;
}
}
- tx += rotate == 0 ? imgLLX : imgLLY;
- ty += rotate == 0 ? imgLLY : -imgLLX;
+ tx += (rotate == 0 || rotate == 180) ? imgLLX : imgLLY;
+ ty += (rotate == 0 || rotate == 180) ? imgLLY : -imgLLX;
if (tx != 0 || ty != 0) {
- writePSFmt("{0:.4g} {1:.4g} translate\n", tx, ty);
+ writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
}
if (xScale != 1 || yScale != 1) {
- writePSFmt("{0:.4f} {0:.4f} scale\n", xScale);
+ writePSFmt("{0:.4f} {1:.4f} scale\n", xScale, yScale);
}
if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re W\n",
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re W\n",
clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
} else {
writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1);
}
- writePS("%%EndPageSetup\n");
++seqPage;
break;
@@ -3087,7 +3311,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
ty = -epsY1;
}
if (tx != 0 || ty != 0) {
- writePSFmt("{0:.4g} {1:.4g} translate\n", tx, ty);
+ writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
}
xScale = yScale = 1;
break;
@@ -3101,6 +3325,18 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
rotate = 0;
break;
}
+
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomPageSetup, pageNum,
+ customCodeCbkData))) {
+ writePS(s->getCString());
+ delete s;
+ }
+ }
+
+ if (mode == psModePS) {
+ writePS("%%EndPageSetup\n");
+ }
}
void PSOutputDev::endPage() {
@@ -3109,7 +3345,6 @@ void PSOutputDev::endPage() {
(*overlayCbk)(this, overlayCbkData);
}
-
if (mode == psModeForm) {
writePS("pdfEndPage\n");
writePS("end end\n");
@@ -3136,7 +3371,7 @@ void PSOutputDev::restoreState(GfxState *state) {
void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
double m21, double m22, double m31, double m32) {
- writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] cm\n",
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n",
m11, m12, m21, m22, m31, m32);
}
@@ -3148,11 +3383,11 @@ void PSOutputDev::updateLineDash(GfxState *state) {
state->getLineDash(&dash, &length, &start);
writePS("[");
for (i = 0; i < length; ++i) {
- writePSFmt("{0:.4g}{1:w}",
+ writePSFmt("{0:.6g}{1:w}",
dash[i] < 0 ? 0 : dash[i],
(i == length-1) ? 0 : 1);
}
- writePSFmt("] {0:.4g} d\n", start);
+ writePSFmt("] {0:.6g} d\n", start);
}
void PSOutputDev::updateFlatness(GfxState *state) {
@@ -3172,7 +3407,7 @@ void PSOutputDev::updateMiterLimit(GfxState *state) {
}
void PSOutputDev::updateLineWidth(GfxState *state) {
- writePSFmt("{0:.4g} w\n", state->getLineWidth());
+ writePSFmt("{0:.6g} w\n", state->getLineWidth());
}
void PSOutputDev::updateFillColorSpace(GfxState *state) {
@@ -3408,9 +3643,9 @@ void PSOutputDev::updateTransfer(GfxState *state) {
void PSOutputDev::updateFont(GfxState *state) {
if (state->getFont()) {
- writePSFmt("/F{0:d}_{1:d} {2:.4g} Tf\n",
+ writePSFmt("/F{0:d}_{1:d} {2:.6g} Tf\n",
state->getFont()->getID()->num, state->getFont()->getID()->gen,
- fabs(state->getFontSize()) < 0.00001 ? 0.00001
+ fabs(state->getFontSize()) < 0.0001 ? 0.0001
: state->getFontSize());
}
}
@@ -3421,15 +3656,15 @@ void PSOutputDev::updateTextMat(GfxState *state) {
mat = state->getTextMat();
if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) {
// avoid a singular (or close-to-singular) matrix
- writePSFmt("[0.00001 0 0 0.00001 {0:.4g} {1:.4g}] Tm\n", mat[4], mat[5]);
+ writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] Tm\n", mat[4], mat[5]);
} else {
- writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] Tm\n",
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] Tm\n",
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
}
}
void PSOutputDev::updateCharSpace(GfxState *state) {
- writePSFmt("{0:.4g} Tc\n", state->getCharSpace());
+ writePSFmt("{0:.6g} Tc\n", state->getCharSpace());
}
void PSOutputDev::updateRender(GfxState *state) {
@@ -3444,11 +3679,11 @@ void PSOutputDev::updateRender(GfxState *state) {
}
void PSOutputDev::updateRise(GfxState *state) {
- writePSFmt("{0:.4g} Ts\n", state->getRise());
+ writePSFmt("{0:.6g} Ts\n", state->getRise());
}
void PSOutputDev::updateWordSpace(GfxState *state) {
- writePSFmt("{0:.4g} Tw\n", state->getWordSpace());
+ writePSFmt("{0:.6g} Tw\n", state->getWordSpace());
}
void PSOutputDev::updateHorizScaling(GfxState *state) {
@@ -3458,25 +3693,33 @@ void PSOutputDev::updateHorizScaling(GfxState *state) {
if (fabs(h) < 0.01) {
h = 0.01;
}
- writePSFmt("{0:.4g} Tz\n", h);
+ writePSFmt("{0:.6g} Tz\n", h);
}
void PSOutputDev::updateTextPos(GfxState *state) {
- writePSFmt("{0:.4g} {1:.4g} Td\n", state->getLineX(), state->getLineY());
+ writePSFmt("{0:.6g} {1:.6g} Td\n", state->getLineX(), state->getLineY());
}
void PSOutputDev::updateTextShift(GfxState *state, double shift) {
if (state->getFont()->getWMode()) {
- writePSFmt("{0:.4g} TJmV\n", shift);
+ writePSFmt("{0:.6g} TJmV\n", shift);
} else {
- writePSFmt("{0:.4g} TJm\n", shift);
+ writePSFmt("{0:.6g} TJm\n", shift);
}
}
+void PSOutputDev::saveTextPos(GfxState *state) {
+ writePS("currentpoint\n");
+}
+
+void PSOutputDev::restoreTextPos(GfxState *state) {
+ writePS("m\n");
+}
+
void PSOutputDev::stroke(GfxState *state) {
doPath(state->getPath());
- if (t3String) {
- // if we're construct a cacheable Type 3 glyph, we need to do
+ if (inType3Char && t3FillColorOnly) {
+ // if we're constructing a cacheable Type 3 glyph, we need to do
// everything in the fill color
writePS("Sf\n");
} else {
@@ -3494,19 +3737,19 @@ void PSOutputDev::eoFill(GfxState *state) {
writePS("f*\n");
}
-void PSOutputDev::tilingPatternFill(GfxState *state, Object *str,
+void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
int paintType, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
double xStep, double yStep) {
PDFRectangle box;
- Gfx *gfx;
+ Gfx *gfx2;
// define a Type 3 font
writePS("8 dict begin\n");
writePS("/FontType 3 def\n");
writePS("/FontMatrix [1 0 0 1 0 0] def\n");
- writePSFmt("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n",
bbox[0], bbox[1], bbox[2], bbox[3]);
writePS("/Encoding 256 array def\n");
writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
@@ -3526,34 +3769,37 @@ void PSOutputDev::tilingPatternFill(GfxState *state, Object *str,
box.y1 = bbox[1];
box.x2 = bbox[2];
box.y2 = bbox[3];
- gfx = new Gfx(xref, this, resDict, &box, NULL);
+ gfx2 = new Gfx(doc, this, resDict, &box, NULL);
writePS("/x {\n");
if (paintType == 2) {
- writePSFmt("{0:.4g} 0 {1:.4g} {2:.4g} {3:.4g} {4:.4g} setcachedevice\n",
+ writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n",
xStep, bbox[0], bbox[1], bbox[2], bbox[3]);
+ t3FillColorOnly = gTrue;
} else {
if (x1 - 1 <= x0) {
writePS("1 0 setcharwidth\n");
} else {
- writePSFmt("{0:.4g} 0 setcharwidth\n", xStep);
+ writePSFmt("{0:.6g} 0 setcharwidth\n", xStep);
}
+ t3FillColorOnly = gFalse;
}
inType3Char = gTrue;
++numTilingPatterns;
- gfx->display(str);
+ gfx2->display(str);
--numTilingPatterns;
inType3Char = gFalse;
writePS("} def\n");
- delete gfx;
+ delete gfx2;
writePS("end\n");
writePS("currentdict end\n");
writePSFmt("/xpdfTile{0:d} exch definefont pop\n", numTilingPatterns);
// draw the tiles
writePSFmt("/xpdfTile{0:d} findfont setfont\n", numTilingPatterns);
- writePSFmt("gsave [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] concat\n",
+ writePS("fCol\n");
+ writePSFmt("gsave [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- writePSFmt("{0:d} 1 {1:d} {{ {2:.4g} exch {3:.4g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n",
+ writePSFmt("{0:d} 1 {1:d} {{ {2:.6g} exch {3:.6g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n",
y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1);
writePS("grestore\n");
}
@@ -3573,7 +3819,7 @@ GBool PSOutputDev::functionShadedFill(GfxState *state,
shading->getDomain(&x0, &y0, &x1, &y1);
mat = shading->getMatrix();
- writePSFmt("/mat [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] def\n",
+ writePSFmt("/mat [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n",
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
if (shading->getNFuncs() == 1) {
@@ -3594,7 +3840,7 @@ GBool PSOutputDev::functionShadedFill(GfxState *state,
}
writePS("} def\n");
}
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} 0 funcSH\n", x0, y0, x1, y1);
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} 0 funcSH\n", x0, y0, x1, y1);
return gTrue;
}
@@ -3656,19 +3902,19 @@ GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) {
t1 = shading->getDomain1();
// generate the PS code
- writePSFmt("/t0 {0:.4g} def\n", t0);
- writePSFmt("/t1 {0:.4g} def\n", t1);
- writePSFmt("/dt {0:.4g} def\n", t1 - t0);
- writePSFmt("/x0 {0:.4g} def\n", x0);
- writePSFmt("/y0 {0:.4g} def\n", y0);
- writePSFmt("/dx {0:.4g} def\n", x1 - x0);
- writePSFmt("/x1 {0:.4g} def\n", x1);
- writePSFmt("/y1 {0:.4g} def\n", y1);
- writePSFmt("/dy {0:.4g} def\n", y1 - y0);
- writePSFmt("/xMin {0:.4g} def\n", xMin);
- writePSFmt("/yMin {0:.4g} def\n", yMin);
- writePSFmt("/xMax {0:.4g} def\n", xMax);
- writePSFmt("/yMax {0:.4g} def\n", yMax);
+ writePSFmt("/t0 {0:.6g} def\n", t0);
+ writePSFmt("/t1 {0:.6g} def\n", t1);
+ writePSFmt("/dt {0:.6g} def\n", t1 - t0);
+ writePSFmt("/x0 {0:.6g} def\n", x0);
+ writePSFmt("/y0 {0:.6g} def\n", y0);
+ writePSFmt("/dx {0:.6g} def\n", x1 - x0);
+ writePSFmt("/x1 {0:.6g} def\n", x1);
+ writePSFmt("/y1 {0:.6g} def\n", y1);
+ writePSFmt("/dy {0:.6g} def\n", y1 - y0);
+ writePSFmt("/xMin {0:.6g} def\n", xMin);
+ writePSFmt("/yMin {0:.6g} def\n", yMin);
+ writePSFmt("/xMax {0:.6g} def\n", xMax);
+ writePSFmt("/yMax {0:.6g} def\n", yMax);
writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
if (shading->getNFuncs() == 1) {
writePS("/func ");
@@ -3688,7 +3934,7 @@ GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) {
}
writePS("} def\n");
}
- writePSFmt("{0:.4g} {1:.4g} 0 axialSH\n", tMin, tMax);
+ writePSFmt("{0:.6g} {1:.6g} 0 axialSH\n", tMin, tMax);
return gTrue;
}
@@ -3698,7 +3944,10 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
double xMin, yMin, xMax, yMax;
double x0, y0, r0, x1, y1, r1, t0, t1;
double xa, ya, ra;
- double sz, xz, yz, sMin, sMax, sa, ta;
+ double sz, sMin, sMax, h, ta;
+ double sLeft, sRight, sTop, sBottom, sZero, sDiag;
+ GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
+ GBool haveSMin, haveSMax;
double theta, alpha, a1, a2;
GBool enclosed;
int i;
@@ -3717,19 +3966,23 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
// Compute the point at which r(s) = 0; check for the enclosed
// circles case; and compute the angles for the tangent lines.
- if (r0 == r1) {
- enclosed = x0 == x1 && y0 == y1;
+ h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
+ if (h == 0) {
+ enclosed = gTrue;
+ theta = 0; // make gcc happy
+ sz = 0; // make gcc happy
+ } else if (r1 - r0 == 0) {
+ enclosed = gFalse;
theta = 0;
sz = 0; // make gcc happy
+ } else if (fabs(r1 - r0) >= h) {
+ enclosed = gTrue;
+ theta = 0; // make gcc happy
+ sz = 0; // make gcc happy
} else {
+ enclosed = gFalse;
sz = -r0 / (r1 - r0);
- xz = x0 + sz * (x1 - x0);
- yz = y0 + sz * (y1 - y0);
- enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0;
- theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz)));
- if (r0 > r1) {
- theta = -theta;
- }
+ theta = asin((r1 - r0) / h);
}
if (enclosed) {
a1 = 0;
@@ -3749,80 +4002,122 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
sMin = 0;
sMax = 1;
} else {
- sMin = 1;
- sMax = 0;
- // solve for x(s) + r(s) = xMin
- if ((x1 + r1) - (x0 + r0) != 0) {
- sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for x(s) - r(s) = xMax
- if ((x1 - r1) - (x0 - r0) != 0) {
- sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for y(s) + r(s) = yMin
- if ((y1 + r1) - (y0 + r0) != 0) {
- sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for y(s) - r(s) = yMax
- if ((y1 - r1) - (y0 - r0) != 0) {
- sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // check against sz
- if (r0 < r1) {
- if (sMin < sz) {
- sMin = sz;
- }
- } else if (r0 > r1) {
- if (sMax > sz) {
- sMax = sz;
- }
- }
- // check the 'extend' flags
- if (!shading->getExtend0() && sMin < 0) {
+ // solve x(sLeft) + r(sLeft) = xMin
+ if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
+ sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
+ } else {
+ sLeft = 0; // make gcc happy
+ }
+ // solve x(sRight) - r(sRight) = xMax
+ if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
+ sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
+ } else {
+ sRight = 0; // make gcc happy
+ }
+ // solve y(sBottom) + r(sBottom) = yMin
+ if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
+ sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
+ } else {
+ sBottom = 0; // make gcc happy
+ }
+ // solve y(sTop) - r(sTop) = yMax
+ if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
+ sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
+ } else {
+ sTop = 0; // make gcc happy
+ }
+ // solve r(sZero) = 0
+ if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
+ sZero = -r0 / (r1 - r0);
+ } else {
+ sZero = 0; // make gcc happy
+ }
+ // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
+ if (haveSZero) {
+ sDiag = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ } else {
+ sDiag = 0; // make gcc happy
+ }
+ // compute sMin
+ if (shading->getExtend0()) {
+ sMin = 0;
+ haveSMin = gFalse;
+ if (x0 < x1 && haveSLeft && sLeft < 0) {
+ sMin = sLeft;
+ haveSMin = gTrue;
+ } else if (x0 > x1 && haveSRight && sRight < 0) {
+ sMin = sRight;
+ haveSMin = gTrue;
+ }
+ if (y0 < y1 && haveSBottom && sBottom < 0) {
+ if (!haveSMin || sBottom > sMin) {
+ sMin = sBottom;
+ haveSMin = gTrue;
+ }
+ } else if (y0 > y1 && haveSTop && sTop < 0) {
+ if (!haveSMin || sTop > sMin) {
+ sMin = sTop;
+ haveSMin = gTrue;
+ }
+ }
+ if (haveSZero && sZero < 0) {
+ if (!haveSMin || sZero > sMin) {
+ sMin = sZero;
+ }
+ }
+ } else {
sMin = 0;
}
- if (!shading->getExtend1() && sMax > 1) {
+ // compute sMax
+ if (shading->getExtend1()) {
+ sMax = 1;
+ haveSMax = gFalse;
+ if (x1 < x0 && haveSLeft && sLeft > 1) {
+ sMax = sLeft;
+ haveSMax = gTrue;
+ } else if (x1 > x0 && haveSRight && sRight > 1) {
+ sMax = sRight;
+ haveSMax = gTrue;
+ }
+ if (y1 < y0 && haveSBottom && sBottom > 1) {
+ if (!haveSMax || sBottom < sMax) {
+ sMax = sBottom;
+ haveSMax = gTrue;
+ }
+ } else if (y1 > y0 && haveSTop && sTop > 1) {
+ if (!haveSMax || sTop < sMax) {
+ sMax = sTop;
+ haveSMax = gTrue;
+ }
+ }
+ if (haveSZero && sDiag > 1) {
+ if (!haveSMax || sDiag < sMax) {
+ sMax = sDiag;
+ }
+ }
+ } else {
sMax = 1;
}
}
// generate the PS code
- writePSFmt("/x0 {0:.4g} def\n", x0);
- writePSFmt("/x1 {0:.4g} def\n", x1);
- writePSFmt("/dx {0:.4g} def\n", x1 - x0);
- writePSFmt("/y0 {0:.4g} def\n", y0);
- writePSFmt("/y1 {0:.4g} def\n", y1);
- writePSFmt("/dy {0:.4g} def\n", y1 - y0);
- writePSFmt("/r0 {0:.4g} def\n", r0);
- writePSFmt("/r1 {0:.4g} def\n", r1);
- writePSFmt("/dr {0:.4g} def\n", r1 - r0);
- writePSFmt("/t0 {0:.4g} def\n", t0);
- writePSFmt("/t1 {0:.4g} def\n", t1);
- writePSFmt("/dt {0:.4g} def\n", t1 - t0);
+ writePSFmt("/x0 {0:.6g} def\n", x0);
+ writePSFmt("/x1 {0:.6g} def\n", x1);
+ writePSFmt("/dx {0:.6g} def\n", x1 - x0);
+ writePSFmt("/y0 {0:.6g} def\n", y0);
+ writePSFmt("/y1 {0:.6g} def\n", y1);
+ writePSFmt("/dy {0:.6g} def\n", y1 - y0);
+ writePSFmt("/r0 {0:.6g} def\n", r0);
+ writePSFmt("/r1 {0:.6g} def\n", r1);
+ writePSFmt("/dr {0:.6g} def\n", r1 - r0);
+ writePSFmt("/t0 {0:.6g} def\n", t0);
+ writePSFmt("/t1 {0:.6g} def\n", t1);
+ writePSFmt("/dt {0:.6g} def\n", t1 - t0);
writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
writePSFmt("/encl {0:s} def\n", enclosed ? "true" : "false");
- writePSFmt("/a1 {0:.4g} def\n", a1);
- writePSFmt("/a2 {0:.4g} def\n", a2);
+ writePSFmt("/a1 {0:.6g} def\n", a1);
+ writePSFmt("/a2 {0:.6g} def\n", a2);
if (shading->getNFuncs() == 1) {
writePS("/func ");
cvtFunction(shading->getFunc(0));
@@ -3841,7 +4136,7 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
}
writePS("} def\n");
}
- writePSFmt("{0:.4g} {1:.4g} 0 radialSH\n", sMin, sMax);
+ writePSFmt("{0:.6g} {1:.6g} 0 radialSH\n", sMin, sMax);
// extend the 'enclosed' case
if (enclosed) {
@@ -3860,11 +4155,11 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
ya = y1;
}
if (level == psLevel2Sep || level == psLevel3Sep) {
- writePSFmt("{0:.4g} radialCol aload pop k\n", ta);
+ writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
} else {
- writePSFmt("{0:.4g} radialCol sc\n", ta);
+ writePSFmt("{0:.6g} radialCol sc\n", ta);
}
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} 0 360 arc h f*\n", xa, ya, ra);
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h f*\n", xa, ya, ra);
}
// extend the larger circle
@@ -3882,12 +4177,12 @@ GBool PSOutputDev::radialShadedFill(GfxState *state,
ya = y1;
}
if (level == psLevel2Sep || level == psLevel3Sep) {
- writePSFmt("{0:.4g} radialCol aload pop k\n", ta);
+ writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
} else {
- writePSFmt("{0:.4g} radialCol sc\n", ta);
+ writePSFmt("{0:.6g} radialCol sc\n", ta);
}
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} 0 360 arc h\n", xa, ya, ra);
- writePSFmt("{0:.4g} {1:.4g} m {2:.4g} {3:.4g} l {4:.4g} {5:.4g} l {6:.4g} {7:.4g} l h f*\n",
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h\n", xa, ya, ra);
+ writePSFmt("{0:.6g} {1:.6g} m {2:.6g} {3:.6g} l {4:.6g} {5:.6g} l {6:.6g} {7:.6g} l h f*\n",
xMin, yMin, xMin, yMax, xMax, yMax, xMax, yMin);
}
}
@@ -3931,12 +4226,12 @@ void PSOutputDev::doPath(GfxPath *path) {
x3 = subpath->getX(3);
y3 = subpath->getY(3);
if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re\n",
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
fabs(x2 - x0), fabs(y1 - y0));
return;
} else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re\n",
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
fabs(x1 - x0), fabs(y2 - y0));
return;
@@ -3947,17 +4242,17 @@ void PSOutputDev::doPath(GfxPath *path) {
for (i = 0; i < n; ++i) {
subpath = path->getSubpath(i);
m = subpath->getNumPoints();
- writePSFmt("{0:.4g} {1:.4g} m\n", subpath->getX(0), subpath->getY(0));
+ writePSFmt("{0:.6g} {1:.6g} m\n", subpath->getX(0), subpath->getY(0));
j = 1;
while (j < m) {
if (subpath->getCurve(j)) {
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} c\n",
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} c\n",
subpath->getX(j), subpath->getY(j),
subpath->getX(j+1), subpath->getY(j+1),
subpath->getX(j+2), subpath->getY(j+2));
j += 3;
} else {
- writePSFmt("{0:.4g} {1:.4g} l\n", subpath->getX(j), subpath->getY(j));
+ writePSFmt("{0:.6g} {1:.6g} l\n", subpath->getX(j), subpath->getY(j));
++j;
}
}
@@ -3970,15 +4265,16 @@ void PSOutputDev::doPath(GfxPath *path) {
void PSOutputDev::drawString(GfxState *state, GString *s) {
GfxFont *font;
int wMode;
- Gushort *codeToGID;
+ int *codeToGID;
GString *s2;
- double dx, dy, dx2, dy2, originX, originY;
+ double dx, dy, originX, originY;
char *p;
UnicodeMap *uMap;
CharCode code;
Unicode u[8];
char buf[8];
- int len, nChars, uLen, n, m, i, j;
+ double *dxdy;
+ int dxdySize, len, nChars, uLen, n, m, i, j;
// check for invisible text -- this is used by Acrobat Capture
if (state->getRender() == 3) {
@@ -4003,6 +4299,10 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
for (i = 0; i < font16EncLen; ++i) {
if (font->getID()->num == font16Enc[i].fontID.num &&
font->getID()->gen == font16Enc[i].fontID.gen) {
+ if (!font16Enc[i].enc) {
+ // font substitution failed, so don't output any text
+ return;
+ }
uMap = globalParams->getUnicodeMap(font16Enc[i].enc);
break;
}
@@ -4019,63 +4319,89 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
}
}
- // compute width of chars in string, ignoring char spacing and word
- // spacing -- the Tj operator will adjust for the metrics of the
- // font that's actually used
- dx = dy = 0;
+ // compute the positioning (dx, dy) for each char in the string
nChars = 0;
p = s->getCString();
len = s->getLength();
s2 = new GString();
+ dxdySize = font->isCIDFont() ? 8 : s->getLength();
+ dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double));
while (len > 0) {
n = font->getNextChar(p, len, &code,
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
- &dx2, &dy2, &originX, &originY);
+ &dx, &dy, &originX, &originY);
+ dx *= state->getFontSize();
+ dy *= state->getFontSize();
+ if (wMode) {
+ dy += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dy += state->getWordSpace();
+ }
+ } else {
+ dx += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ }
+ dx *= state->getHorizScaling();
if (font->isCIDFont()) {
if (uMap) {
+ if (nChars + uLen > dxdySize) {
+ do {
+ dxdySize *= 2;
+ } while (nChars + uLen > dxdySize);
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
for (i = 0; i < uLen; ++i) {
m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
for (j = 0; j < m; ++j) {
s2->append(buf[j]);
}
+ //~ this really needs to get the number of chars in the target
+ //~ encoding - which may be more than the number of Unicode
+ //~ chars
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
}
- //~ this really needs to get the number of chars in the target
- //~ encoding - which may be more than the number of Unicode
- //~ chars
- nChars += uLen;
} else {
+ if (nChars + 1 > dxdySize) {
+ dxdySize *= 2;
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
s2->append((char)((code >> 8) & 0xff));
s2->append((char)(code & 0xff));
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
++nChars;
}
} else {
- if (!codeToGID || codeToGID[code]) {
+ if (!codeToGID || codeToGID[code] >= 0) {
s2->append((char)code);
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
}
}
- dx += dx2;
- dy += dy2;
p += n;
len -= n;
}
- dx *= state->getFontSize() * state->getHorizScaling();
- dy *= state->getFontSize();
if (uMap) {
uMap->decRefCnt();
}
- if (s2->getLength() > 0) {
+ if (nChars > 0) {
writePSString(s2);
- if (font->isCIDFont()) {
- if (wMode) {
- writePSFmt(" {0:d} {1:.4g} Tj16V\n", nChars, dy);
- } else {
- writePSFmt(" {0:d} {1:.4g} Tj16\n", nChars, dx);
+ writePS("\n[");
+ for (i = 0; i < 2 * nChars; ++i) {
+ if (i > 0) {
+ writePS("\n");
}
- } else {
- writePSFmt(" {0:.4g} Tj\n", dx);
+ writePSFmt("{0:.6g}", dxdy[i]);
}
+ writePS("] Tj\n");
}
+ gfree(dxdy);
delete s2;
if (state->getRender() & 4) {
@@ -4301,7 +4627,7 @@ void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
width, -height, height);
// allocate a line buffer
- lineBuf = (Guchar *)gmalloc(4 * width);
+ lineBuf = (Guchar *)gmallocn(width, 4);
// set up to process the data stream
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
@@ -4730,24 +5056,32 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
// data source
if (mode == psModeForm || inType3Char || preload) {
- writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
+ writePS(" /DataSource { pdfImStr }\n");
} else {
writePS(" /DataSource currentfile\n");
}
// filters
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- useRLE = gTrue;
- useASCII = !(mode == psModeForm || inType3Char || preload);
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ useRLE = gFalse;
useCompressed = gFalse;
+ useASCII = gFalse;
} else {
- useRLE = gFalse;
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preload);
- useCompressed = gTrue;
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+ " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+ inlineImg || !s) {
+ useRLE = gTrue;
+ useASCII = !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gFalse;
+ } else {
+ useRLE = gFalse;
+ useASCII = str->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gTrue;
+ }
}
if (useASCII) {
writePSFmt(" /ASCII{0:s}Decode filter\n",
@@ -4803,7 +5137,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
if (opi13Nest) {
if (inlineImg) {
// this can't happen -- OPI dictionaries are in XObjects
- error(-1, "Internal: OPI in inline image");
+ error(errSyntaxError, -1, "OPI in inline image");
n = 0;
} else {
// need to read the stream to count characters -- the length
@@ -4872,6 +5206,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
int n, numComps;
GBool useRLE, useASCII, useASCIIHex, useCompressed;
GBool maskUseRLE, maskUseASCII, maskUseCompressed;
+ GString *maskFilters;
GfxSeparationColorSpace *sepCS;
GfxColor color;
GfxCMYK cmyk;
@@ -4881,6 +5216,83 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
useASCIIHex = globalParams->getPSASCIIHex();
useRLE = useASCII = useCompressed = gFalse; // make gcc happy
maskUseRLE = maskUseASCII = maskUseCompressed = gFalse; // make gcc happy
+ maskFilters = NULL; // make gcc happy
+
+ // explicit masking
+ if (maskStr) {
+
+ // mask data source
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ maskUseRLE = gFalse;
+ maskUseCompressed = gFalse;
+ maskUseASCII = gFalse;
+ } else {
+ s = maskStr->getPSFilter(3, " ");
+ if (!s) {
+ maskUseRLE = gTrue;
+ maskUseASCII = !(mode == psModeForm || inType3Char || preload);
+ maskUseCompressed = gFalse;
+ } else {
+ maskUseRLE = gFalse;
+ maskUseASCII = maskStr->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ maskUseCompressed = gTrue;
+ }
+ }
+ maskFilters = new GString();
+ if (maskUseASCII) {
+ maskFilters->appendf(" /ASCII{0:s}Decode filter\n",
+ useASCIIHex ? "Hex" : "85");
+ }
+ if (maskUseRLE) {
+ maskFilters->append(" /RunLengthDecode filter\n");
+ }
+ if (maskUseCompressed) {
+ maskFilters->append(s);
+ }
+ if (s) {
+ delete s;
+ }
+ if (mode == psModeForm || inType3Char || preload) {
+ writePSFmt("MaskData_{0:d}_{1:d} pdfMaskInit\n",
+ ref->getRefNum(), ref->getRefGen());
+ } else {
+ writePS("currentfile\n");
+ writePS(maskFilters->getCString());
+ writePS("pdfMask\n");
+
+ // add RunLengthEncode and ASCIIHex/85 encode filters
+ if (maskUseCompressed) {
+ maskStr = maskStr->getUndecodedStream();
+ }
+ if (maskUseRLE) {
+ maskStr = new RunLengthEncoder(maskStr);
+ }
+ if (maskUseASCII) {
+ if (useASCIIHex) {
+ maskStr = new ASCIIHexEncoder(maskStr);
+ } else {
+ maskStr = new ASCII85Encoder(maskStr);
+ }
+ }
+
+ // copy the stream data
+ maskStr->reset();
+ while ((c = maskStr->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ maskStr->close();
+ writePSChar('\n');
+ writePS("%-EOD-\n");
+
+ // delete encoders
+ if (maskUseRLE || maskUseASCII) {
+ delete maskStr;
+ }
+ }
+ }
// color space
if (colorMap) {
@@ -5015,24 +5427,32 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
// data source
if (mode == psModeForm || inType3Char || preload) {
- writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
+ writePS(" /DataSource { pdfImStr }\n");
} else {
writePS(" /DataSource currentfile\n");
}
// filters
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- useRLE = gTrue;
- useASCII = !(mode == psModeForm || inType3Char || preload);
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ useRLE = gFalse;
useCompressed = gFalse;
+ useASCII = gFalse;
} else {
- useRLE = gFalse;
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preload);
- useCompressed = gTrue;
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+ " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+ inlineImg || !s) {
+ useRLE = gTrue;
+ useASCII = !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gFalse;
+ } else {
+ useRLE = gFalse;
+ useASCII = str->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gTrue;
+ }
}
if (useASCII) {
writePSFmt(" /ASCII{0:s}Decode filter\n",
@@ -5065,30 +5485,13 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
maskInvert ? 1 : 0, maskInvert ? 0 : 1);
// mask data source
- writePS(" /DataSource currentfile\n");
- s = maskStr->getPSFilter(3, " ");
- if (!s) {
- maskUseRLE = gTrue;
- maskUseASCII = gTrue;
- maskUseCompressed = gFalse;
+ if (mode == psModeForm || inType3Char || preload) {
+ writePS(" /DataSource {pdfMaskSrc}\n");
+ writePS(maskFilters->getCString());
} else {
- maskUseRLE = gFalse;
- maskUseASCII = maskStr->isBinary();
- maskUseCompressed = gTrue;
- }
- if (maskUseASCII) {
- writePSFmt(" /ASCII{0:s}Decode filter\n",
- useASCIIHex ? "Hex" : "85");
- }
- if (maskUseRLE) {
- writePS(" /RunLengthDecode filter\n");
- }
- if (maskUseCompressed) {
- writePS(s->getCString());
- }
- if (s) {
- delete s;
+ writePS(" /DataSource maskStream\n");
}
+ delete maskFilters;
writePS(">>\n");
writePS(">>\n");
@@ -5116,39 +5519,6 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
}
- // explicit masking
- if (maskStr) {
-
- if (maskUseCompressed) {
- maskStr = maskStr->getUndecodedStream();
- }
-
- // add RunLengthEncode and ASCIIHex/85 encode filters
- if (maskUseRLE) {
- maskStr = new RunLengthEncoder(maskStr);
- }
- if (maskUseASCII) {
- if (useASCIIHex) {
- maskStr = new ASCIIHexEncoder(maskStr);
- } else {
- maskStr = new ASCII85Encoder(maskStr);
- }
- }
-
- // copy the stream data
- maskStr->reset();
- while ((c = maskStr->getChar()) != EOF) {
- writePSChar(c);
- }
- maskStr->close();
- writePSChar('\n');
-
- // delete encoders
- if (maskUseRLE || maskUseASCII) {
- delete maskStr;
- }
- }
-
// get rid of the array and index
if (mode == psModeForm || inType3Char || preload) {
writePS("pop pop\n");
@@ -5196,6 +5566,13 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
delete str;
}
}
+
+ // close the mask stream
+ if (maskStr) {
+ if (!(mode == psModeForm || inType3Char || preload)) {
+ writePS("pdfMaskEnd\n");
+ }
+ }
}
void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
@@ -5506,7 +5883,7 @@ void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
obj1.arrayGet(1, &obj2);
height = obj2.getNum();
obj2.free();
- writePSFmt("%%ImageDimensions: {0:.4g} {1:.4g}\n", width, height);
+ writePSFmt("%%ImageDimensions: {0:.6g} {1:.6g}\n", width, height);
}
obj1.free();
@@ -5524,7 +5901,7 @@ void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
obj1.arrayGet(3, &obj2);
bottom = obj2.getNum();
obj2.free();
- writePSFmt("%%ImageCropRect: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n",
+ writePSFmt("%%ImageCropRect: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n",
left, top, right, bottom);
}
obj1.free();
@@ -5883,7 +6260,7 @@ GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) {
#endif // OPI_SUPPORT
void PSOutputDev::type3D0(GfxState *state, double wx, double wy) {
- writePSFmt("{0:.4g} {1:.4g} setcharwidth\n", wx, wy);
+ writePSFmt("{0:.6g} {1:.6g} setcharwidth\n", wx, wy);
writePS("q\n");
t3NeedsRestore = gTrue;
}
@@ -5898,6 +6275,7 @@ void PSOutputDev::type3D1(GfxState *state, double wx, double wy,
t3URY = ury;
t3String = new GString();
writePS("q\n");
+ t3FillColorOnly = gTrue;
t3Cacheable = gTrue;
t3NeedsRestore = gTrue;
}
@@ -5948,14 +6326,14 @@ void PSOutputDev::cvtFunction(Function *func) {
}
writePSFmt("/xpdfSamples{0:d} [\n", thisFunc);
for (i = 0; i < nSamples; ++i) {
- writePSFmt("{0:.4g}\n", func0->getSamples()[i]);
+ writePSFmt("{0:.6g}\n", func0->getSamples()[i]);
}
writePS("] def\n");
writePSFmt("{{ {0:d} array {1:d} array {2:d} 2 roll\n", 2*m, m, m+2);
// [e01] [efrac] x0 x1 ... xm-1
for (i = m-1; i >= 0; --i) {
// [e01] [efrac] x0 x1 ... xi
- writePSFmt("{0:.4g} sub {1:.4g} mul {2:.4g} add\n",
+ writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add\n",
func0->getDomainMin(i),
(func0->getEncodeMax(i) - func0->getEncodeMin(i)) /
(func0->getDomainMax(i) - func0->getDomainMin(i)),
@@ -6000,15 +6378,15 @@ void PSOutputDev::cvtFunction(Function *func) {
writePSFmt("{0:d} index {1:d} get dup\n",
i + k/2 + (1 << (m-j)) - k, j);
writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n");
- writePSFmt("{0:d} 1 roll\n", k/2 + (1 << m-j) - k - 1);
+ writePSFmt("{0:d} 1 roll\n", k/2 + (1 << (m-j)) - k - 1);
}
// [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1)
}
// [e01] [efrac] y(0) ... y(i-1) s
- writePSFmt("{0:.4g} mul {1:.4g} add\n",
+ writePSFmt("{0:.6g} mul {1:.6g} add\n",
func0->getDecodeMax(i) - func0->getDecodeMin(i),
func0->getDecodeMin(i));
- writePSFmt("dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n",
+ writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
func0->getRangeMin(i), func0->getRangeMin(i),
func0->getRangeMax(i), func0->getRangeMax(i));
// [e01] [efrac] y(0) ... y(i-1) y(i)
@@ -6020,17 +6398,17 @@ void PSOutputDev::cvtFunction(Function *func) {
case 2: // exponential
func2 = (ExponentialFunction *)func;
n = func2->getOutputSize();
- writePSFmt("{{ dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n",
+ writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
func2->getDomainMin(0), func2->getDomainMin(0),
func2->getDomainMax(0), func2->getDomainMax(0));
// x
for (i = 0; i < n; ++i) {
// x y(0) .. y(i-1)
- writePSFmt("{0:d} index {1:.4g} exp {2:.4g} mul {3:.4g} add\n",
+ writePSFmt("{0:d} index {1:.6g} exp {2:.6g} mul {3:.6g} add\n",
i, func2->getE(), func2->getC1()[i] - func2->getC0()[i],
func2->getC0()[i]);
if (func2->getHasRange()) {
- writePSFmt("dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n",
+ writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
func2->getRangeMin(i), func2->getRangeMin(i),
func2->getRangeMax(i), func2->getRangeMax(i));
}
@@ -6046,18 +6424,18 @@ void PSOutputDev::cvtFunction(Function *func) {
cvtFunction(func3->getFunc(i));
writePSFmt("/xpdfFunc{0:d}_{1:d} exch def\n", thisFunc, i);
}
- writePSFmt("{{ dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n",
+ writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
func3->getDomainMin(0), func3->getDomainMin(0),
func3->getDomainMax(0), func3->getDomainMax(0));
for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
- writePSFmt("dup {0:.4g} lt {{ {1:.4g} sub {2:.4g} mul {3:.4g} add xpdfFunc{4:d}_{5:d} }} {{\n",
+ writePSFmt("dup {0:.6g} lt {{ {1:.6g} sub {2:.6g} mul {3:.6g} add xpdfFunc{4:d}_{5:d} }} {{\n",
func3->getBounds()[i+1],
func3->getBounds()[i],
func3->getScale()[i],
func3->getEncode()[2*i],
thisFunc, i);
}
- writePSFmt("{0:.4g} sub {1:.4g} mul {2:.4g} add xpdfFunc{3:d}_{4:d}\n",
+ writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add xpdfFunc{3:d}_{4:d}\n",
func3->getBounds()[i],
func3->getScale()[i],
func3->getEncode()[2*i],
@@ -6084,11 +6462,11 @@ void PSOutputDev::writePSChar(char c) {
}
}
-void PSOutputDev::writePS(char *s) {
+void PSOutputDev::writePS(const char *s) {
if (t3String) {
t3String->append(s);
} else {
- (*outputFunc)(outputStream, s, strlen(s));
+ (*outputFunc)(outputStream, s, (int)strlen(s));
}
}
@@ -6136,8 +6514,8 @@ void PSOutputDev::writePSString(GString *s) {
writePSChar(')');
}
-void PSOutputDev::writePSName(char *s) {
- char *p;
+void PSOutputDev::writePSName(const char *s) {
+ const char *p;
char c;
p = s;
diff --git a/xpdf/PSOutputDev.h b/xpdf/PSOutputDev.h
index 67b4d98..e528f8c 100644
--- a/xpdf/PSOutputDev.h
+++ b/xpdf/PSOutputDev.h
@@ -21,15 +21,20 @@
#include "GlobalParams.h"
#include "OutputDev.h"
+class GHash;
+class PDFDoc;
+class XRef;
class Function;
class GfxPath;
class GfxFont;
class GfxColorSpace;
class GfxSeparationColorSpace;
class PDFRectangle;
+struct PST1FontName;
struct PSFont8Info;
struct PSFont16Enc;
class PSOutCustomColor;
+class PSOutputDev;
//------------------------------------------------------------------------
// PSOutputDev
@@ -48,25 +53,38 @@ enum PSFileType {
psGeneric // write to a generic stream
};
-typedef void (*PSOutputFunc)(void *stream, char *data, int len);
+enum PSOutCustomCodeLocation {
+ psOutCustomDocSetup,
+ psOutCustomPageSetup
+};
+
+typedef void (*PSOutputFunc)(void *stream, const char *data, int len);
+
+typedef GString *(*PSOutCustomCodeCbk)(PSOutputDev *psOut,
+ PSOutCustomCodeLocation loc, int n,
+ void *data);
class PSOutputDev: public OutputDev {
public:
// Open a PostScript output file, and write the prolog.
- PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
+ PSOutputDev(char *fileName, PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA = 0, int imgLLYA = 0,
int imgURXA = 0, int imgURYA = 0,
- GBool manualCtrlA = gFalse);
+ GBool manualCtrlA = gFalse,
+ PSOutCustomCodeCbk customCodeCbkA = NULL,
+ void *customCodeCbkDataA = NULL);
// Open a PSOutputDev that will write to a generic stream.
PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
- XRef *xrefA, Catalog *catalog,
+ PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA = 0, int imgLLYA = 0,
int imgURXA = 0, int imgURYA = 0,
- GBool manualCtrlA = gFalse);
+ GBool manualCtrlA = gFalse,
+ PSOutCustomCodeCbk customCodeCbkA = NULL,
+ void *customCodeCbkDataA = NULL);
// Destructor -- writes the trailer and closes the file.
virtual ~PSOutputDev();
@@ -130,7 +148,7 @@ public:
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 printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
@@ -171,12 +189,14 @@ public:
virtual void updateHorizScaling(GfxState *state);
virtual void updateTextPos(GfxState *state);
virtual void updateTextShift(GfxState *state, double shift);
+ virtual void saveTextPos(GfxState *state);
+ virtual void restoreTextPos(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
- virtual void tilingPatternFill(GfxState *state, Object *str,
+ virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
int paintType, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
@@ -241,10 +261,16 @@ public:
void *data)
{ overlayCbk = cbk; overlayCbkData = data; }
+ void writePSChar(char c);
+ void writePS(const char *s);
+ void writePSFmt(const char *fmt, ...);
+ void writePSString(GString *s);
+ void writePSName(const char *s);
+
private:
void init(PSOutputFunc outputFuncA, void *outputStreamA,
- PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ PSFileType fileTypeA, PDFDoc *docA,
int firstPage, int lastPage, PSOutMode modeA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA);
@@ -256,14 +282,20 @@ private:
void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GString *psName);
void setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GString *psName);
void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GString *psName);
- void setupExternalTrueTypeFont(GfxFont *font, GString *psName);
+ void setupExternalTrueTypeFont(GfxFont *font, GString *fileName,
+ GString *psName);
void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GString *psName);
void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GString *psName,
GBool needVerticalMetrics);
+ void setupExternalCIDTrueTypeFont(GfxFont *font,
+ GString *fileName,
+ GString *psName,
+ GBool needVerticalMetrics);
void setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GString *psName);
void setupType3Font(GfxFont *font, GString *psName, Dict *parentResDict);
+ GString *makePSFontName(GfxFont *font, Ref *id);
void setupImages(Dict *resDict);
- void setupImage(Ref id, Stream *str);
+ void setupImage(Ref id, Stream *str, GBool mask);
void setupForms(Dict *resDict);
void setupForm(Ref id, Object *strObj);
void addProcessColor(double c, double m, double y, double k);
@@ -296,11 +328,6 @@ private:
GBool getFileSpec(Object *fileSpec, Object *fileName);
#endif
void cvtFunction(Function *func);
- void writePSChar(char c);
- void writePS(char *s);
- void writePSFmt(const char *fmt, ...);
- void writePSString(GString *s);
- void writePSName(char *s);
GString *filterPSName(GString *name);
void writePSTextLine(GString *s);
@@ -308,6 +335,7 @@ private:
PSOutMode mode; // PostScript mode (PS, EPS, form)
int paperWidth; // width of paper, in pts
int paperHeight; // height of paper, in pts
+ GBool paperMatch; // true if paper size is set to match each page
int imgLLX, imgLLY, // imageable area, in pts
imgURX, imgURY;
GBool preload; // load all images into memory, and
@@ -322,20 +350,21 @@ private:
void *underlayCbkData;
void (*overlayCbk)(PSOutputDev *psOut, void *data);
void *overlayCbkData;
+ GString *(*customCodeCbk)(PSOutputDev *psOut,
+ PSOutCustomCodeLocation loc, int n,
+ void *data);
+ void *customCodeCbkData;
+ PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
Ref *fontIDs; // list of object IDs of all used fonts
int fontIDLen; // number of entries in fontIDs array
int fontIDSize; // size of fontIDs array
- Ref *fontFileIDs; // list of object IDs of all embedded fonts
- int fontFileIDLen; // number of entries in fontFileIDs array
- int fontFileIDSize; // size of fontFileIDs array
- GString **fontFileNames; // list of names of all embedded external fonts
- int fontFileNameLen; // number of entries in fontFileNames array
- int fontFileNameSize; // size of fontFileNames array
- int nextTrueTypeNum; // next unique number to append to a TrueType
- // font name
+ GHash *fontNames; // all used font names
+ PST1FontName *t1FontNames; // font names for Type 1/1C fonts
+ int t1FontNameLen; // number of entries in t1FontNames array
+ int t1FontNameSize; // size of t1FontNames array
PSFont8Info *font8Info; // info for 8-bit fonts
int font8InfoLen; // number of entries in font8Info array
int font8InfoSize; // size of font8Info array
@@ -354,6 +383,8 @@ private:
int numTilingPatterns; // current number of nested tiling patterns
int nextFunc; // next unique number to use for a function
+ GList *paperSizes; // list of used paper sizes, if paperMatch
+ // is true [PSOutPaperSize]
double tx0, ty0; // global translation
double xScale0, yScale0; // global scaling
int rotate0; // rotation angle (0, 90, 180, 270)
@@ -378,6 +409,7 @@ private:
GString *t3String; // Type 3 content string
double t3WX, t3WY, // Type 3 character parameters
t3LLX, t3LLY, t3URX, t3URY;
+ GBool t3FillColorOnly; // operators should only use the fill color
GBool t3Cacheable; // cleared if char is not cacheable
GBool t3NeedsRestore; // set if a 'q' operator was issued
@@ -388,7 +420,6 @@ private:
GBool ok; // set up ok?
-
friend class WinPDFPrinter;
};
diff --git a/xpdf/Page.cc b/xpdf/Page.cc
index c930665..189d2a2 100644
--- a/xpdf/Page.cc
+++ b/xpdf/Page.cc
@@ -17,6 +17,7 @@
#include "Object.h"
#include "Array.h"
#include "Dict.h"
+#include "PDFDoc.h"
#include "XRef.h"
#include "Link.h"
#include "OutputDev.h"
@@ -102,12 +103,6 @@ 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()) {
@@ -138,6 +133,24 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
obj1.free();
}
+PageAttrs::PageAttrs() {
+ mediaBox.x1 = mediaBox.y1 = 0;
+ mediaBox.x2 = mediaBox.y2 = 50;
+ cropBox = mediaBox;
+ haveCropBox = gFalse;
+ bleedBox = cropBox;
+ trimBox = cropBox;
+ artBox = cropBox;
+ rotate = 0;
+ lastModified.initNull();
+ boxColorInfo.initNull();
+ group.initNull();
+ metadata.initNull();
+ pieceInfo.initNull();
+ separationInfo.initNull();
+ resources.initNull();
+}
+
PageAttrs::~PageAttrs() {
lastModified.free();
boxColorInfo.free();
@@ -148,7 +161,14 @@ PageAttrs::~PageAttrs() {
resources.free();
}
-GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
+void PageAttrs::clipBoxes() {
+ cropBox.clipTo(&mediaBox);
+ bleedBox.clipTo(&mediaBox);
+ trimBox.clipTo(&mediaBox);
+ artBox.clipTo(&mediaBox);
+}
+
+GBool PageAttrs::readBox(Dict *dict, const char *key, PDFRectangle *box) {
PDFRectangle tmp;
double t;
Object obj1, obj2;
@@ -205,18 +225,21 @@ GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
// Page
//------------------------------------------------------------------------
-Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
+Page::Page(PDFDoc *docA, int numA, Dict *pageDict, PageAttrs *attrsA) {
ok = gTrue;
- xref = xrefA;
+ doc = docA;
+ xref = doc->getXRef();
num = numA;
// get attributes
attrs = attrsA;
+ attrs->clipBoxes();
// annotations
pageDict->lookupNF("Annots", &annots);
if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
- error(-1, "Page annotations object (page %d) is wrong type (%s)",
+ error(errSyntaxError, -1,
+ "Page annotations object (page {0:d}) is wrong type ({1:s})",
num, annots.getTypeName());
annots.free();
goto err2;
@@ -226,7 +249,8 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
pageDict->lookupNF("Contents", &contents);
if (!(contents.isRef() || contents.isArray() ||
contents.isNull())) {
- error(-1, "Page contents object (page %d) is wrong type (%s)",
+ error(errSyntaxError, -1,
+ "Page contents object (page {0:d}) is wrong type ({1:s})",
num, contents.getTypeName());
contents.free();
goto err1;
@@ -241,35 +265,45 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
ok = gFalse;
}
+Page::Page(PDFDoc *docA, int numA) {
+ doc = docA;
+ xref = doc->getXRef();
+ num = numA;
+ attrs = new PageAttrs();
+ annots.initNull();
+ contents.initNull();
+ ok = gTrue;
+}
+
Page::~Page() {
delete attrs;
annots.free();
contents.free();
}
-Links *Page::getLinks(Catalog *catalog) {
+Links *Page::getLinks() {
Links *links;
Object obj;
- links = new Links(getAnnots(&obj), catalog->getBaseURI());
+ links = new Links(getAnnots(&obj), doc->getCatalog()->getBaseURI());
obj.free();
return links;
}
void Page::display(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
- GBool printing, Catalog *catalog,
+ GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- -1, -1, -1, -1, printing, catalog,
+ -1, -1, -1, -1, printing,
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,
- GBool printing, Catalog *catalog,
+ GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
#ifndef PDF_PARSER_ONLY
@@ -283,8 +317,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
- printing, catalog,
- abortCheckCbk, abortCheckCbkData)) {
+ printing, abortCheckCbk, abortCheckCbkData)) {
return;
}
@@ -308,7 +341,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
printf("***** Rotate = %d\n", attrs->getRotate());
}
- gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
+ gfx = new Gfx(doc, out, num, attrs->getResourceDict(),
hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
rotate, abortCheckCbk, abortCheckCbkData);
contents.fetch(xref, &obj);
@@ -316,32 +349,38 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
gfx->saveState();
gfx->display(&obj);
gfx->restoreState();
+ } else {
+ // empty pages need to call dump to do any setup required by the
+ // OutputDev
+ out->dump();
}
obj.free();
// 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);
- }
- }
+ if (globalParams->getDrawAnnotations()) {
+ annotList = new Annots(doc, getAnnots(&obj));
obj.free();
- }
- if (annotList->getNumAnnots() > 0) {
- if (globalParams->getPrintCommands()) {
- printf("***** Annotations\n");
+ acroForm = doc->getCatalog()->getAcroForm()->isDict() ?
+ doc->getCatalog()->getAcroForm()->getDict() : NULL;
+ if (acroForm) {
+ if (acroForm->lookup("NeedAppearances", &obj)) {
+ if (obj.isBool() && obj.getBool()) {
+ annotList->generateAppearances();
+ }
+ }
+ obj.free();
}
- for (i = 0; i < annotList->getNumAnnots(); ++i) {
- annotList->getAnnot(i)->draw(gfx, printing);
+ if (annotList->getNumAnnots() > 0) {
+ if (globalParams->getPrintCommands()) {
+ printf("***** Annotations\n");
+ }
+ for (i = 0; i < annotList->getNumAnnots(); ++i) {
+ annotList->getAnnot(i)->draw(gfx, printing);
+ }
+ out->dump();
}
- out->dump();
+ delete annotList;
}
- delete annotList;
delete gfx;
#endif
@@ -409,13 +448,13 @@ void Page::makeBox(double hDPI, double vDPI, int rotate,
}
}
-void Page::processLinks(OutputDev *out, Catalog *catalog) {
+void Page::processLinks(OutputDev *out) {
Links *links;
int i;
- links = getLinks(catalog);
+ links = getLinks();
for (i = 0; i < links->getNumLinks(); ++i) {
- out->processLink(links->getLink(i), catalog);
+ out->processLink(links->getLink(i));
}
delete links;
}
diff --git a/xpdf/Page.h b/xpdf/Page.h
index 2b01175..102eca8 100644
--- a/xpdf/Page.h
+++ b/xpdf/Page.h
@@ -18,10 +18,10 @@
#include "Object.h"
class Dict;
+class PDFDoc;
class XRef;
class OutputDev;
class Links;
-class Catalog;
//------------------------------------------------------------------------
@@ -48,6 +48,10 @@ public:
// <attrs> is NULL, uses defaults.
PageAttrs(PageAttrs *attrs, Dict *dict);
+ // Construct a new PageAttrs object for an empty page (only used
+ // when there is an error in the page tree).
+ PageAttrs();
+
// Destructor.
~PageAttrs();
@@ -76,9 +80,12 @@ public:
Dict *getResourceDict()
{ return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
+ // Clip all other boxes to the MediaBox.
+ void clipBoxes();
+
private:
- GBool readBox(Dict *dict, char *key, PDFRectangle *box);
+ GBool readBox(Dict *dict, const char *key, PDFRectangle *box);
PDFRectangle mediaBox;
PDFRectangle cropBox;
@@ -104,7 +111,11 @@ class Page {
public:
// Constructor.
- Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA);
+ Page(PDFDoc *docA, int numA, Dict *pageDict, PageAttrs *attrsA);
+
+ // Create an empty page (only used when there is an error in the
+ // page tree).
+ Page(PDFDoc *docA, int numA);
// Destructor.
~Page();
@@ -143,7 +154,7 @@ public:
Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
// Return a list of links.
- Links *getLinks(Catalog *catalog);
+ Links *getLinks();
// Get contents.
Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
@@ -151,7 +162,7 @@ public:
// Display a page.
void display(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
- GBool printing, Catalog *catalog,
+ GBool printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
@@ -159,7 +170,7 @@ public:
void displaySlice(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
- GBool printing, Catalog *catalog,
+ GBool printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
@@ -168,7 +179,7 @@ public:
double sliceX, double sliceY, double sliceW, double sliceH,
PDFRectangle *box, GBool *crop);
- void processLinks(OutputDev *out, Catalog *catalog);
+ void processLinks(OutputDev *out);
// Get the page's default CTM.
void getDefaultCTM(double *ctm, double hDPI, double vDPI,
@@ -176,6 +187,7 @@ public:
private:
+ PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
int num; // page number
PageAttrs *attrs; // page attributes
diff --git a/xpdf/Parser.cc b/xpdf/Parser.cc
index c1fc715..c43da26 100644
--- a/xpdf/Parser.cc
+++ b/xpdf/Parser.cc
@@ -21,6 +21,10 @@
#include "XRef.h"
#include "Error.h"
+// Max number of nested objects. This is used to catch infinite loops
+// in the object structure.
+#define recursionLimit 500
+
Parser::Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA) {
xref = xrefA;
lexer = lexerA;
@@ -36,9 +40,10 @@ Parser::~Parser() {
delete lexer;
}
-Object *Parser::getObj(Object *obj, Guchar *fileKey,
+Object *Parser::getObj(Object *obj, GBool simpleOnly,
+ Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength,
- int objNum, int objGen) {
+ int objNum, int objGen, int recursion) {
char *key;
Stream *str;
Object obj2;
@@ -57,23 +62,24 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
}
// array
- if (buf1.isCmd("[")) {
+ if (!simpleOnly && recursion < recursionLimit && buf1.isCmd("[")) {
shift();
obj->initArray(xref);
while (!buf1.isCmd("]") && !buf1.isEOF())
- obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength,
- objNum, objGen));
+ obj->arrayAdd(getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength,
+ objNum, objGen, recursion + 1));
if (buf1.isEOF())
- error(getPos(), "End of file inside array");
+ error(errSyntaxError, getPos(), "End of file inside array");
shift();
// dictionary or stream
- } else if (buf1.isCmd("<<")) {
+ } else if (!simpleOnly && recursion < recursionLimit && buf1.isCmd("<<")) {
shift();
obj->initDict(xref);
while (!buf1.isCmd(">>") && !buf1.isEOF()) {
if (!buf1.isName()) {
- error(getPos(), "Dictionary key must be a name object");
+ error(errSyntaxError, getPos(),
+ "Dictionary key must be a name object");
shift();
} else {
key = copyString(buf1.getName());
@@ -82,17 +88,18 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
gfree(key);
break;
}
- obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength,
- objNum, objGen));
+ obj->dictAdd(key, getObj(&obj2, gFalse,
+ fileKey, encAlgorithm, keyLength,
+ objNum, objGen, recursion + 1));
}
}
if (buf1.isEOF())
- error(getPos(), "End of file inside dictionary");
+ error(errSyntaxError, getPos(), "End of file inside dictionary");
// 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))) {
+ objNum, objGen, recursion + 1))) {
obj->initStream(str);
} else {
obj->free();
@@ -142,7 +149,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength,
- int objNum, int objGen) {
+ int objNum, int objGen, int recursion) {
Object obj;
BaseStream *baseStr;
Stream *str;
@@ -150,15 +157,18 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
// get stream start position
lexer->skipToNextLine();
- pos = lexer->getPos();
+ if (!(str = lexer->getStream())) {
+ return NULL;
+ }
+ pos = str->getPos();
// get length
- dict->dictLookup("Length", &obj);
+ dict->dictLookup("Length", &obj, recursion);
if (obj.isInt()) {
length = (Guint)obj.getInt();
obj.free();
} else {
- error(getPos(), "Bad 'Length' attribute in stream");
+ error(errSyntaxError, getPos(), "Bad 'Length' attribute in stream");
obj.free();
return NULL;
}
@@ -184,7 +194,7 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
if (buf1.isCmd("endstream")) {
shift();
} else {
- error(getPos(), "Missing 'endstream'");
+ error(errSyntaxError, getPos(), "Missing 'endstream'");
// kludge for broken PDF files: just add 5k to the length, and
// hope its enough
length += 5000;
diff --git a/xpdf/Parser.h b/xpdf/Parser.h
index a109558..b25d749 100644
--- a/xpdf/Parser.h
+++ b/xpdf/Parser.h
@@ -30,10 +30,13 @@ public:
// Destructor.
~Parser();
- // Get the next object from the input stream.
- Object *getObj(Object *obj, Guchar *fileKey = NULL,
+ // Get the next object from the input stream. If <simpleOnly> is
+ // true, do not parse compound objects (arrays, dictionaries, or
+ // streams).
+ Object *getObj(Object *obj, GBool simpleOnly = gFalse,
+ Guchar *fileKey = NULL,
CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
- int objNum = 0, int objGen = 0);
+ int objNum = 0, int objGen = 0, int recursion = 0);
// Get stream.
Stream *getStream() { return lexer->getStream(); }
@@ -51,7 +54,7 @@ private:
Stream *makeStream(Object *dict, Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength,
- int objNum, int objGen);
+ int objNum, int objGen, int recursion);
void shift();
};
diff --git a/xpdf/PreScanOutputDev.cc b/xpdf/PreScanOutputDev.cc
index 7dd7bf5..bf48df0 100644
--- a/xpdf/PreScanOutputDev.cc
+++ b/xpdf/PreScanOutputDev.cc
@@ -14,6 +14,8 @@
#include <math.h>
#include "GlobalParams.h"
+#include "Page.h"
+#include "Gfx.h"
#include "GfxFont.h"
#include "Link.h"
#include "PreScanOutputDev.h"
@@ -58,6 +60,62 @@ void PreScanOutputDev::eoFill(GfxState *state) {
state->getFillOpacity(), state->getBlendMode());
}
+void PreScanOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx,
+ Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep) {
+ if (paintType == 1) {
+ gfx->drawForm(str, resDict, mat, bbox);
+ } else {
+ check(state->getFillColorSpace(), state->getFillColor(),
+ state->getFillOpacity(), state->getBlendMode());
+ }
+}
+
+GBool PreScanOutputDev::functionShadedFill(GfxState *state,
+ GfxFunctionShading *shading) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
+GBool PreScanOutputDev::axialShadedFill(GfxState *state,
+ GfxAxialShading *shading) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
+GBool PreScanOutputDev::radialShadedFill(GfxState *state,
+ GfxRadialShading *shading) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
void PreScanOutputDev::clip(GfxState *state) {
//~ check for a rectangle "near" the edge of the page;
//~ else set gdi to false
@@ -71,8 +129,6 @@ void PreScanOutputDev::beginStringOp(GfxState *state) {
int render;
GfxFont *font;
double m11, m12, m21, m22;
- Ref embRef;
- DisplayFontParam *dfp;
GBool simpleTTF;
render = state->getRender();
@@ -87,18 +143,14 @@ void PreScanOutputDev::beginStringOp(GfxState *state) {
font = state->getFont();
state->getFontTransMat(&m11, &m12, &m21, &m22);
+ //~ this should check for external fonts that are non-TrueType
simpleTTF = fabs(m11 + m22) < 0.01 &&
m11 > 0 &&
fabs(m12) < 0.01 &&
fabs(m21) < 0.01 &&
fabs(state->getHorizScaling() - 1) < 0.001 &&
(font->getType() == fontTrueType ||
- font->getType() == fontTrueTypeOT) &&
- (font->getEmbeddedFontID(&embRef) ||
- font->getExtFontFile() ||
- (font->getName() &&
- (dfp = globalParams->getDisplayFont(font->getName())) &&
- dfp->kind == displayFontTT));
+ font->getType() == fontTrueTypeOT);
if (simpleTTF) {
//~ need to create a FoFiTrueType object, and check for a Unicode cmap
}
@@ -127,6 +179,9 @@ void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
check(state->getFillColorSpace(), state->getFillColor(),
state->getFillOpacity(), state->getBlendMode());
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ patternImgMask = gTrue;
+ }
gdi = gFalse;
if (inlineImg) {
@@ -149,12 +204,17 @@ void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
if (colorSpace->getMode() == csIndexed) {
colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
}
- if (colorSpace->getMode() != csDeviceGray &&
- colorSpace->getMode() != csCalGray) {
+ if (colorSpace->getMode() == csDeviceGray ||
+ colorSpace->getMode() == csCalGray) {
+ if (colorMap->getBits() > 1) {
+ mono = gFalse;
+ }
+ } else {
gray = gFalse;
+ mono = gFalse;
}
- mono = gFalse;
- if (state->getBlendMode() != gfxBlendNormal) {
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
transparency = gTrue;
}
gdi = gFalse;
@@ -182,12 +242,17 @@ void PreScanOutputDev::drawMaskedImage(GfxState *state, Object *ref,
if (colorSpace->getMode() == csIndexed) {
colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
}
- if (colorSpace->getMode() != csDeviceGray &&
- colorSpace->getMode() != csCalGray) {
+ if (colorSpace->getMode() == csDeviceGray ||
+ colorSpace->getMode() == csCalGray) {
+ if (colorMap->getBits() > 1) {
+ mono = gFalse;
+ }
+ } else {
gray = gFalse;
+ mono = gFalse;
}
- mono = gFalse;
- if (state->getBlendMode() != gfxBlendNormal) {
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
transparency = gTrue;
}
gdi = gFalse;
@@ -253,5 +318,6 @@ void PreScanOutputDev::clearStats() {
mono = gTrue;
gray = gTrue;
transparency = gFalse;
+ patternImgMask = gFalse;
gdi = gTrue;
}
diff --git a/xpdf/PreScanOutputDev.h b/xpdf/PreScanOutputDev.h
index c825ddf..3889cfc 100644
--- a/xpdf/PreScanOutputDev.h
+++ b/xpdf/PreScanOutputDev.h
@@ -41,6 +41,16 @@ public:
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gTrue; }
+ // Does this device use tilingPatternFill()? If this returns false,
+ // tiling pattern fills will be reduced to a series of other drawing
+ // operations.
+ virtual GBool useTilingPatternFill() { return gTrue; }
+
+ // Does this device use functionShadedFill(), axialShadedFill(), and
+ // radialShadedFill()? If this returns false, these shaded fills
+ // will be reduced to a series of other drawing operations.
+ virtual GBool useShadedFills() { return gTrue; }
+
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
@@ -57,6 +67,15 @@ public:
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
+ virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep);
+ virtual GBool functionShadedFill(GfxState *state,
+ GfxFunctionShading *shading);
+ virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading);
+ virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading);
//----- path clipping
virtual void clip(GfxState *state);
@@ -110,6 +129,11 @@ public:
GBool usesTransparency() { return transparency; }
// Returns true if the operations performed since the last call to
+ // clearStats() included any image mask fills with a pattern color
+ // space.
+ GBool usesPatternImageMask() { return patternImgMask; }
+
+ // Returns true if the operations performed since the last call to
// clearStats() are all rasterizable by GDI calls in GDIOutputDev.
GBool isAllGDI() { return gdi; }
@@ -124,6 +148,7 @@ private:
GBool mono;
GBool gray;
GBool transparency;
+ GBool patternImgMask;
GBool gdi;
};
diff --git a/xpdf/SecurityHandler.cc b/xpdf/SecurityHandler.cc
index ea0f934..52607c2 100644
--- a/xpdf/SecurityHandler.cc
+++ b/xpdf/SecurityHandler.cc
@@ -17,11 +17,7 @@
#include "Decrypt.h"
#include "Error.h"
#include "GlobalParams.h"
-#if HAVE_XPDFCORE
-# include "XPDFCore.h"
-#elif HAVE_WINPDFCORE
-# include "WinPDFCore.h"
-#endif
+#include "PDFCore.h"
#ifdef ENABLE_PLUGINS
# include "XpdfPluginAPI.h"
#endif
@@ -47,14 +43,15 @@ SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh);
} else {
#endif
- error(-1, "Couldn't find the '%s' security handler",
+ error(errSyntaxError, -1, "Couldn't find the '{0:s}' security handler",
filterObj.getName());
secHdlr = NULL;
#ifdef ENABLE_PLUGINS
}
#endif
} else {
- error(-1, "Missing or invalid 'Filter' entry in encryption dictionary");
+ error(errSyntaxError, -1,
+ "Missing or invalid 'Filter' entry in encryption dictionary");
secHdlr = NULL;
}
filterObj.free();
@@ -93,7 +90,7 @@ GBool SecurityHandler::checkEncryption(GString *ownerPassword,
}
}
if (!ok) {
- error(-1, "Incorrect password");
+ error(errCommandLine, -1, "Incorrect password");
}
return ok;
}
@@ -128,8 +125,8 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
SecurityHandler(docA)
{
Object versionObj, revisionObj, lengthObj;
- Object ownerKeyObj, userKeyObj, permObj, fileIDObj;
- Object fileIDObj1;
+ Object ownerKeyObj, userKeyObj, ownerEncObj, userEncObj;
+ Object permObj, fileIDObj, fileIDObj1;
Object cryptFiltersObj, streamFilterObj, stringFilterObj;
Object cryptFilterObj, cfmObj, cfLengthObj;
Object encryptMetadataObj;
@@ -138,101 +135,152 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
fileID = NULL;
ownerKey = NULL;
userKey = NULL;
+ ownerEnc = NULL;
+ userEnc = NULL;
+ fileKeyLength = 0;
encryptDictA->dictLookup("V", &versionObj);
encryptDictA->dictLookup("R", &revisionObj);
encryptDictA->dictLookup("Length", &lengthObj);
encryptDictA->dictLookup("O", &ownerKeyObj);
encryptDictA->dictLookup("U", &userKeyObj);
+ encryptDictA->dictLookup("OE", &ownerEncObj);
+ encryptDictA->dictLookup("UE", &userEncObj);
encryptDictA->dictLookup("P", &permObj);
doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj);
if (versionObj.isInt() &&
revisionObj.isInt() &&
- ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 &&
- userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 &&
- permObj.isInt()) {
+ permObj.isInt() &&
+ ownerKeyObj.isString() &&
+ userKeyObj.isString()) {
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()) {
- fileKeyLength = 5;
- } else {
- fileKeyLength = lengthObj.getInt() / 8;
- }
- encryptMetadata = gTrue;
- //~ this currently only handles a subset of crypt filter functionality
- if (encVersion == 4 && encRevision == 4) {
- encryptDictA->dictLookup("CF", &cryptFiltersObj);
- encryptDictA->dictLookup("StmF", &streamFilterObj);
- encryptDictA->dictLookup("StrF", &stringFilterObj);
- if (cryptFiltersObj.isDict() &&
- streamFilterObj.isName() &&
- stringFilterObj.isName() &&
- !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
- if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
- &cryptFilterObj)->isDict()) {
- cryptFilterObj.dictLookup("CFM", &cfmObj);
- if (cfmObj.isName("V2")) {
- encVersion = 2;
- encRevision = 3;
- if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
- //~ according to the spec, this should be cfLengthObj / 8
- 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();
+ if ((encRevision <= 4 &&
+ ownerKeyObj.getString()->getLength() == 32 &&
+ userKeyObj.getString()->getLength() == 32) ||
+ (encRevision == 5 &&
+ // the spec says 48 bytes, but Acrobat pads them out longer
+ ownerKeyObj.getString()->getLength() >= 48 &&
+ userKeyObj.getString()->getLength() >= 48 &&
+ ownerEncObj.isString() &&
+ ownerEncObj.getString()->getLength() == 32 &&
+ userEncObj.isString() &&
+ userEncObj.getString()->getLength() == 32)) {
+ encAlgorithm = cryptRC4;
+ // revision 2 forces a 40-bit key - some buggy PDF generators
+ // set the Length value incorrectly
+ if (encRevision == 2 || !lengthObj.isInt()) {
+ fileKeyLength = 5;
+ } else {
+ fileKeyLength = lengthObj.getInt() / 8;
+ }
+ encryptMetadata = gTrue;
+ //~ this currently only handles a subset of crypt filter functionality
+ //~ (in particular, it ignores the EFF entry in encryptDictA, and
+ //~ doesn't handle the case where StmF, StrF, and EFF are not all the
+ //~ same)
+ if ((encVersion == 4 || encVersion == 5) &&
+ (encRevision == 4 || encRevision == 5)) {
+ encryptDictA->dictLookup("CF", &cryptFiltersObj);
+ encryptDictA->dictLookup("StmF", &streamFilterObj);
+ encryptDictA->dictLookup("StrF", &stringFilterObj);
+ if (cryptFiltersObj.isDict() &&
+ streamFilterObj.isName() &&
+ stringFilterObj.isName() &&
+ !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
+ if (!strcmp(streamFilterObj.getName(), "Identity")) {
+ // no encryption on streams or strings
+ encVersion = encRevision = -1;
+ } else {
+ if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
+ &cryptFilterObj)->isDict()) {
+ cryptFilterObj.dictLookup("CFM", &cfmObj);
+ if (cfmObj.isName("V2")) {
+ encVersion = 2;
+ encRevision = 3;
+ if (cryptFilterObj.dictLookup("Length",
+ &cfLengthObj)->isInt()) {
+ //~ according to the spec, this should be cfLengthObj / 8
+ 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();
+ } else if (cfmObj.isName("AESV3")) {
+ encVersion = 5;
+ encRevision = 5;
+ encAlgorithm = cryptAES256;
+ if (cryptFilterObj.dictLookup("Length",
+ &cfLengthObj)->isInt()) {
+ //~ according to the spec, this should be cfLengthObj / 8
+ fileKeyLength = cfLengthObj.getInt();
+ }
+ cfLengthObj.free();
+ }
+ cfmObj.free();
}
- cfLengthObj.free();
+ cryptFilterObj.free();
}
- cfmObj.free();
}
- cryptFilterObj.free();
- }
- stringFilterObj.free();
- streamFilterObj.free();
- cryptFiltersObj.free();
- if (encryptDictA->dictLookup("EncryptMetadata",
- &encryptMetadataObj)->isBool()) {
- encryptMetadata = encryptMetadataObj.getBool();
+ stringFilterObj.free();
+ streamFilterObj.free();
+ cryptFiltersObj.free();
+ if (encryptDictA->dictLookup("EncryptMetadata",
+ &encryptMetadataObj)->isBool()) {
+ encryptMetadata = encryptMetadataObj.getBool();
+ }
+ encryptMetadataObj.free();
}
- encryptMetadataObj.free();
- }
- permFlags = permObj.getInt();
- ownerKey = ownerKeyObj.getString()->copy();
- userKey = userKeyObj.getString()->copy();
- if (encVersion >= 1 && encVersion <= 2 &&
- encRevision >= 2 && encRevision <= 3) {
- if (fileIDObj.isArray()) {
- if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) {
- fileID = fileIDObj1.getString()->copy();
+ permFlags = permObj.getInt();
+ ownerKey = ownerKeyObj.getString()->copy();
+ userKey = userKeyObj.getString()->copy();
+ if (encVersion >= 1 && encVersion <= 2 &&
+ encRevision >= 2 && encRevision <= 3) {
+ if (fileIDObj.isArray()) {
+ if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) {
+ fileID = fileIDObj1.getString()->copy();
+ } else {
+ fileID = new GString();
+ }
+ fileIDObj1.free();
} else {
fileID = new GString();
}
- fileIDObj1.free();
- } else {
- fileID = new GString();
+ if (fileKeyLength > 16 || fileKeyLength < 0) {
+ fileKeyLength = 16;
+ }
+ ok = gTrue;
+ } else if (encVersion == 5 && encRevision == 5) {
+ fileID = new GString(); // unused for V=R=5
+ ownerEnc = ownerEncObj.getString()->copy();
+ userEnc = userEncObj.getString()->copy();
+ if (fileKeyLength > 32 || fileKeyLength < 0) {
+ fileKeyLength = 32;
+ }
+ ok = gTrue;
+ } else if (!(encVersion == -1 && encRevision == -1)) {
+ error(errUnimplemented, -1,
+ "Unsupported version/revision ({0:d}/{1:d}) of Standard security handler",
+ encVersion, encRevision);
}
- ok = gTrue;
} else {
- error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
- encVersion, encRevision);
+ error(errSyntaxError, -1, "Invalid encryption key length");
}
} else {
- error(-1, "Weird encryption info");
- }
- if (fileKeyLength > 16) {
- fileKeyLength = 16;
+ error(errSyntaxError, -1, "Weird encryption info");
}
fileIDObj.free();
permObj.free();
+ userEncObj.free();
+ ownerEncObj.free();
userKeyObj.free();
ownerKeyObj.free();
lengthObj.free();
@@ -250,6 +298,16 @@ StandardSecurityHandler::~StandardSecurityHandler() {
if (userKey) {
delete userKey;
}
+ if (ownerEnc) {
+ delete ownerEnc;
+ }
+ if (userEnc) {
+ delete userEnc;
+ }
+}
+
+GBool StandardSecurityHandler::isUnencrypted() {
+ return encVersion == -1 && encRevision == -1;
}
void *StandardSecurityHandler::makeAuthData(GString *ownerPassword,
@@ -261,27 +319,14 @@ void *StandardSecurityHandler::makeAuthData(GString *ownerPassword,
}
void *StandardSecurityHandler::getAuthData() {
-#if HAVE_XPDFCORE
- XPDFCore *core;
+ PDFCore *core;
GString *password;
- if (!(core = (XPDFCore *)doc->getGUIData()) ||
+ if (!(core = doc->getCore()) ||
!(password = core->getPassword())) {
return NULL;
}
return new StandardAuthData(password, password->copy());
-#elif HAVE_WINPDFCORE
- WinPDFCore *core;
- GString *password;
-
- if (!(core = (WinPDFCore *)doc->getGUIData()) ||
- !(password = core->getPassword())) {
- return NULL;
- }
- return new StandardAuthData(password, password->copy());
-#else
- return NULL;
-#endif
}
void StandardSecurityHandler::freeAuthData(void *authData) {
@@ -302,7 +347,8 @@ GBool StandardSecurityHandler::authorize(void *authData) {
userPassword = NULL;
}
if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength,
- ownerKey, userKey, permFlags, fileID,
+ ownerKey, userKey, ownerEnc, userEnc,
+ permFlags, fileID,
ownerPassword, userPassword, fileKey,
encryptMetadata, &ownerPasswordOk)) {
return gFalse;
diff --git a/xpdf/SecurityHandler.h b/xpdf/SecurityHandler.h
index a27868c..784a52e 100644
--- a/xpdf/SecurityHandler.h
+++ b/xpdf/SecurityHandler.h
@@ -34,6 +34,9 @@ public:
SecurityHandler(PDFDoc *docA);
virtual ~SecurityHandler();
+ // Returns true if the file is actually unencrypted.
+ virtual GBool isUnencrypted() { return gFalse; }
+
// Check the document's encryption. If the document is encrypted,
// this will first try <ownerPassword> and <userPassword> (in
// "batch" mode), and if those fail, it will attempt to request a
@@ -91,6 +94,7 @@ public:
StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA);
virtual ~StandardSecurityHandler();
+ virtual GBool isUnencrypted();
virtual void *makeAuthData(GString *ownerPassword,
GString *userPassword);
virtual void *getAuthData();
@@ -107,7 +111,7 @@ private:
int permFlags;
GBool ownerPasswordOk;
- Guchar fileKey[16];
+ Guchar fileKey[32];
int fileKeyLength;
int encVersion;
int encRevision;
@@ -115,6 +119,7 @@ private:
GBool encryptMetadata;
GString *ownerKey, *userKey;
+ GString *ownerEnc, *userEnc;
GString *fileID;
GBool ok;
};
diff --git a/xpdf/SplashOutputDev.cc b/xpdf/SplashOutputDev.cc
index e4f86ce..50e4801 100644
--- a/xpdf/SplashOutputDev.cc
+++ b/xpdf/SplashOutputDev.cc
@@ -14,14 +14,18 @@
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "gfile.h"
#include "GlobalParams.h"
#include "Error.h"
#include "Object.h"
+#include "Gfx.h"
#include "GfxFont.h"
#include "Link.h"
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
+#include "BuiltinFont.h"
+#include "BuiltinFontTables.h"
#include "FoFiTrueType.h"
#include "SplashBitmap.h"
#include "SplashGlyphBitmap.h"
@@ -45,6 +49,13 @@ extern "C" int unlink(char *filename);
//------------------------------------------------------------------------
+// Type 3 font cache size parameters
+#define type3FontCacheAssoc 8
+#define type3FontCacheMaxSets 8
+#define type3FontCacheSize (128*1024)
+
+//------------------------------------------------------------------------
+
// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
static inline Guchar div255(int x) {
return (Guchar)((x + (x >> 8) + 0x80) >> 8);
@@ -180,64 +191,100 @@ static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest,
}
}
-static void cvtRGBToHSV(Guchar r, Guchar g, Guchar b, int *h, int *s, int *v) {
- int cmax, cmid, cmin, x;
+static int getLum(int r, int g, int b) {
+ return (int)(0.3 * r + 0.59 * g + 0.11 * b);
+}
- if (r >= g) {
- if (g >= b) { x = 0; cmax = r; cmid = g; cmin = b; }
- else if (b >= r) { x = 4; cmax = b; cmid = r; cmin = g; }
- else { x = 5; cmax = r; cmid = b; cmin = g; }
- } else {
- if (r >= b) { x = 1; cmax = g; cmid = r; cmin = b; }
- else if (g >= b) { x = 2; cmax = g; cmid = b; cmin = r; }
- else { x = 3; cmax = b; cmid = g; cmin = r; }
+static int getSat(int r, int g, int b) {
+ int rgbMin, rgbMax;
+
+ rgbMin = rgbMax = r;
+ if (g < rgbMin) {
+ rgbMin = g;
+ } else if (g > rgbMax) {
+ rgbMax = g;
+ }
+ if (b < rgbMin) {
+ rgbMin = b;
+ } else if (b > rgbMax) {
+ rgbMax = b;
+ }
+ return rgbMax - rgbMin;
+}
+
+static void clipColor(int rIn, int gIn, int bIn,
+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
+ int lum, rgbMin, rgbMax;
+
+ lum = getLum(rIn, gIn, bIn);
+ rgbMin = rgbMax = rIn;
+ if (gIn < rgbMin) {
+ rgbMin = gIn;
+ } else if (gIn > rgbMax) {
+ rgbMax = gIn;
+ }
+ if (bIn < rgbMin) {
+ rgbMin = bIn;
+ } else if (bIn > rgbMax) {
+ rgbMax = bIn;
}
- if (cmax == cmin) {
- *h = *s = 0;
+ if (rgbMin < 0) {
+ *rOut = (Guchar)(lum + ((rIn - lum) * lum) / (lum - rgbMin));
+ *gOut = (Guchar)(lum + ((gIn - lum) * lum) / (lum - rgbMin));
+ *bOut = (Guchar)(lum + ((bIn - lum) * lum) / (lum - rgbMin));
+ } else if (rgbMax > 255) {
+ *rOut = (Guchar)(lum + ((rIn - lum) * (255 - lum)) / (rgbMax - lum));
+ *gOut = (Guchar)(lum + ((gIn - lum) * (255 - lum)) / (rgbMax - lum));
+ *bOut = (Guchar)(lum + ((bIn - lum) * (255 - lum)) / (rgbMax - lum));
} else {
- *h = x * 60;
- if (x & 1) {
- *h += ((cmax - cmid) * 60) / (cmax - cmin);
- } else {
- *h += ((cmid - cmin) * 60) / (cmax - cmin);
- }
- *s = (255 * (cmax - cmin)) / cmax;
+ *rOut = rIn;
+ *gOut = gIn;
+ *bOut = bIn;
}
- *v = cmax;
}
-static void cvtHSVToRGB(int h, int s, int v, Guchar *r, Guchar *g, Guchar *b) {
- int x, f, cmax, cmid, cmin;
+static void setLum(Guchar rIn, Guchar gIn, Guchar bIn, int lum,
+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
+ int d;
+
+ d = lum - getLum(rIn, gIn, bIn);
+ clipColor(rIn + d, gIn + d, bIn + d, rOut, gOut, bOut);
+}
+
+static void setSat(Guchar rIn, Guchar gIn, Guchar bIn, int sat,
+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
+ int rgbMin, rgbMid, rgbMax;
+ Guchar *minOut, *midOut, *maxOut;
- if (s == 0) {
- *r = *g = *b = v;
+ if (rIn < gIn) {
+ rgbMin = rIn; minOut = rOut;
+ rgbMid = gIn; midOut = gOut;
} else {
- x = h / 60;
- f = h % 60;
- cmax = v;
- if (x & 1) {
- cmid = div255(v * 255 - ((s * f) / 60));
- } else {
- cmid = div255(v * (255 - ((s * (60 - f)) / 60)));
- }
- cmin = div255(v * (255 - s));
- switch (x) {
- case 0: *r = cmax; *g = cmid; *b = cmin; break;
- case 1: *g = cmax; *r = cmid; *b = cmin; break;
- case 2: *g = cmax; *b = cmid; *r = cmin; break;
- case 3: *b = cmax; *g = cmid; *r = cmin; break;
- case 4: *b = cmax; *r = cmid; *g = cmin; break;
- case 5: *r = cmax; *b = cmid; *g = cmin; break;
- }
+ rgbMin = gIn; minOut = gOut;
+ rgbMid = rIn; midOut = rOut;
+ }
+ if (bIn > rgbMid) {
+ rgbMax = bIn; maxOut = bOut;
+ } else if (bIn > rgbMin) {
+ rgbMax = rgbMid; maxOut = midOut;
+ rgbMid = bIn; midOut = bOut;
+ } else {
+ rgbMax = rgbMid; maxOut = midOut;
+ rgbMid = rgbMin; midOut = minOut;
+ rgbMin = bIn; minOut = bOut;
+ }
+ if (rgbMax > rgbMin) {
+ *midOut = (Guchar)((rgbMid - rgbMin) * sat) / (rgbMax - rgbMin);
+ *maxOut = (Guchar)sat;
+ } else {
+ *midOut = *maxOut = 0;
}
+ *minOut = 0;
}
static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
+ Guchar r0, g0, b0, r1, g1, b1;
switch (cm) {
case splashModeMono1:
@@ -246,25 +293,22 @@ static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
break;
case splashModeRGB8:
case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hs, sd, vd, &blend[0], &blend[1], &blend[2]);
+ setSat(src[0], src[1], src[2], getSat(dest[0], dest[1], dest[2]),
+ &r0, &g0, &b0);
+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
+ &blend[0], &blend[1], &blend[2]);
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hs, sd, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
+ // NB: inputs have already been converted to additive mode
+ setSat(src[0], src[1], src[2], getSat(dest[0], dest[1], dest[2]),
+ &r0, &g0, &b0);
+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
+ &r1, &g1, &b1);
+ blend[0] = r1;
+ blend[1] = g1;
+ blend[2] = b1;
+ blend[3] = dest[3];
break;
#endif
}
@@ -273,10 +317,7 @@ static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend,
SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
-#if SPLASH_CMYK
- Guchar r, g, b;
-#endif
+ Guchar r0, g0, b0, r1, g1, b1;
switch (cm) {
case splashModeMono1:
@@ -285,25 +326,22 @@ static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
break;
case splashModeRGB8:
case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hd, ss, vd, &blend[0], &blend[1], &blend[2]);
+ setSat(dest[0], dest[1], dest[2], getSat(src[0], src[1], src[2]),
+ &r0, &g0, &b0);
+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
+ &blend[0], &blend[1], &blend[2]);
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hd, ss, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
+ // NB: inputs have already been converted to additive mode
+ setSat(dest[0], dest[1], dest[2], getSat(src[0], src[1], src[2]),
+ &r0, &g0, &b0);
+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
+ &r1, &g1, &b1);
+ blend[0] = r1;
+ blend[1] = g1;
+ blend[2] = b1;
+ blend[3] = dest[3];
break;
#endif
}
@@ -311,7 +349,6 @@ static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
#if SPLASH_CMYK
Guchar r, g, b;
#endif
@@ -323,25 +360,18 @@ static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
break;
case splashModeRGB8:
case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hs, ss, vd, &blend[0], &blend[1], &blend[2]);
+ setLum(src[0], src[1], src[2], getLum(dest[0], dest[1], dest[2]),
+ &blend[0], &blend[1], &blend[2]);
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hs, ss, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
+ // NB: inputs have already been converted to additive mode
+ setLum(src[0], src[1], src[2], getLum(dest[0], dest[1], dest[2]),
+ &r, &g, &b);
+ blend[0] = r;
+ blend[1] = g;
+ blend[2] = b;
+ blend[3] = dest[3];
break;
#endif
}
@@ -350,7 +380,6 @@ static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend,
SplashColorMode cm) {
- int hs, ss, vs, hd, sd, vd;
#if SPLASH_CMYK
Guchar r, g, b;
#endif
@@ -362,25 +391,18 @@ static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest,
break;
case splashModeRGB8:
case splashModeBGR8:
- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
- cvtHSVToRGB(hd, sd, vs, &blend[0], &blend[1], &blend[2]);
+ setLum(dest[0], dest[1], dest[2], getLum(src[0], src[1], src[2]),
+ &blend[0], &blend[1], &blend[2]);
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hd, sd, vs, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
+ // NB: inputs have already been converted to additive mode
+ setLum(dest[0], dest[1], dest[2], getLum(src[0], src[1], src[2]),
+ &r, &g, &b);
+ blend[0] = r;
+ blend[1] = g;
+ blend[2] = b;
+ blend[3] = src[3];
break;
#endif
}
@@ -407,35 +429,6 @@ SplashBlendFunc splashOutBlendFuncs[] = {
};
//------------------------------------------------------------------------
-// Font substitutions
-//------------------------------------------------------------------------
-
-struct SplashOutFontSubst {
- char *name;
- double mWidth;
-};
-
-// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
-static SplashOutFontSubst splashOutSubstFonts[16] = {
- {"Helvetica", 0.833},
- {"Helvetica-Oblique", 0.833},
- {"Helvetica-Bold", 0.889},
- {"Helvetica-BoldOblique", 0.889},
- {"Times-Roman", 0.788},
- {"Times-Italic", 0.722},
- {"Times-Bold", 0.833},
- {"Times-BoldItalic", 0.778},
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576}
-};
-
-//------------------------------------------------------------------------
// SplashOutFontFileID
//------------------------------------------------------------------------
@@ -510,21 +503,23 @@ T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
glyphW = glyphWA;
glyphH = glyphHA;
validBBox = validBBoxA;
+ // sanity check for excessively large glyphs (which most likely
+ // indicate an incorrect BBox)
+ i = glyphW * glyphH;
+ if (i > 100000 || glyphW > INT_MAX / glyphH || glyphW <= 0 || glyphH <= 0) {
+ glyphW = glyphH = 100;
+ validBBox = gFalse;
+ }
if (aa) {
glyphSize = glyphW * glyphH;
} else {
glyphSize = ((glyphW + 7) >> 3) * glyphH;
}
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
+ cacheAssoc = type3FontCacheAssoc;
+ for (cacheSets = type3FontCacheMaxSets;
+ cacheSets > 1 &&
+ cacheSets * cacheAssoc * glyphSize > type3FontCacheSize;
+ cacheSets >>= 1) ;
cacheData = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc,
sizeof(T3FontCacheTag));
@@ -584,6 +579,7 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
colorMode = colorModeA;
bitmapRowPad = bitmapRowPadA;
bitmapTopDown = bitmapTopDownA;
+ bitmapUpsideDown = gFalse;
allowAntialias = allowAntialiasA;
vectorAntialias = allowAntialias &&
globalParams->getVectorAntialias() &&
@@ -591,12 +587,15 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
setupScreenParams(72.0, 72.0);
reverseVideo = reverseVideoA;
splashColorCopy(paperColor, paperColorA);
+ skipHorizText = gFalse;
+ skipRotatedText = gFalse;
xref = NULL;
bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
colorMode != splashModeMono1, bitmapTopDown);
splash = new Splash(bitmap, vectorAntialias, &screenParams);
+ splash->setMinLineWidth(globalParams->getMinLineWidth());
splash->clear(paperColor, 0);
fontEngine = NULL;
@@ -609,6 +608,8 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
textClipPath = NULL;
transpGroupStack = NULL;
+
+ nestCount = 0;
}
void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
@@ -635,7 +636,7 @@ void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
case screenStochasticClustered:
screenParams.type = splashScreenStochasticClustered;
if (screenParams.size < 0) {
- screenParams.size = 100;
+ screenParams.size = 64;
}
if (screenParams.dotRadius < 0) {
screenParams.dotRadius = 2;
@@ -648,7 +649,7 @@ void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
if (hDPI > 299.9 && vDPI > 299.9) {
screenParams.type = splashScreenStochasticClustered;
if (screenParams.size < 0) {
- screenParams.size = 100;
+ screenParams.size = 64;
}
if (screenParams.dotRadius < 0) {
screenParams.dotRadius = 2;
@@ -692,6 +693,8 @@ void SplashOutputDev::startDoc(XRef *xrefA) {
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
globalParams->getEnableFreeType(),
+ globalParams->getDisableFreeTypeHinting()
+ ? splashFTNoHinting : 0,
#endif
allowAntialias &&
globalParams->getAntialias() &&
@@ -723,15 +726,18 @@ void SplashOutputDev::startPage(int pageNum, GfxState *state) {
}
if (splash) {
delete splash;
+ splash = NULL;
}
if (!bitmap || w != bitmap->getWidth() || h != bitmap->getHeight()) {
if (bitmap) {
delete bitmap;
+ bitmap = NULL;
}
bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode,
colorMode != splashModeMono1, bitmapTopDown);
}
splash = new Splash(bitmap, vectorAntialias, &screenParams);
+ splash->setMinLineWidth(globalParams->getMinLineWidth());
if (state) {
ctm = state->getCTM();
mat[0] = (SplashCoord)ctm[0];
@@ -835,7 +841,10 @@ void SplashOutputDev::updateLineDash(GfxState *state) {
}
void SplashOutputDev::updateFlatness(GfxState *state) {
+#if 0 // Acrobat ignores the flatness setting, and always renders curves
+ // with a fairly small flatness value
splash->setFlatness(state->getFlatness());
+#endif
}
void SplashOutputDev::updateLineJoin(GfxState *state) {
@@ -868,14 +877,24 @@ void SplashOutputDev::updateFillColor(GfxState *state) {
GfxCMYK cmyk;
#endif
- state->getFillGray(&gray);
- state->getFillRGB(&rgb);
+ switch (colorMode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ state->getFillGray(&gray);
+ splash->setFillPattern(getColor(gray));
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ state->getFillRGB(&rgb);
+ splash->setFillPattern(getColor(&rgb));
+ break;
#if SPLASH_CMYK
- state->getFillCMYK(&cmyk);
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setFillPattern(getColor(gray, &rgb));
+ case splashModeCMYK8:
+ state->getFillCMYK(&cmyk);
+ splash->setFillPattern(getColor(&cmyk));
+ break;
#endif
+ }
}
void SplashOutputDev::updateStrokeColor(GfxState *state) {
@@ -885,28 +904,41 @@ void SplashOutputDev::updateStrokeColor(GfxState *state) {
GfxCMYK cmyk;
#endif
- state->getStrokeGray(&gray);
- state->getStrokeRGB(&rgb);
+ switch (colorMode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ state->getStrokeGray(&gray);
+ splash->setStrokePattern(getColor(gray));
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ state->getStrokeRGB(&rgb);
+ splash->setStrokePattern(getColor(&rgb));
+ break;
#if SPLASH_CMYK
- state->getStrokeCMYK(&cmyk);
- splash->setStrokePattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setStrokePattern(getColor(gray, &rgb));
+ case splashModeCMYK8:
+ state->getStrokeCMYK(&cmyk);
+ splash->setStrokePattern(getColor(&cmyk));
+ break;
#endif
+ }
}
-#if SPLASH_CMYK
-SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb,
- GfxCMYK *cmyk) {
-#else
-SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
-#endif
- SplashPattern *pattern;
+SplashPattern *SplashOutputDev::getColor(GfxGray gray) {
SplashColor color;
- GfxColorComp r, g, b;
if (reverseVideo) {
gray = gfxColorComp1 - gray;
+ }
+ color[0] = colToByte(gray);
+ return new SplashSolidColor(color);
+}
+
+SplashPattern *SplashOutputDev::getColor(GfxRGB *rgb) {
+ GfxColorComp r, g, b;
+ SplashColor color;
+
+ if (reverseVideo) {
r = gfxColorComp1 - rgb->r;
g = gfxColorComp1 - rgb->g;
b = gfxColorComp1 - rgb->b;
@@ -915,33 +947,58 @@ SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
g = rgb->g;
b = rgb->b;
}
+ color[0] = colToByte(r);
+ color[1] = colToByte(g);
+ color[2] = colToByte(b);
+ return new SplashSolidColor(color);
+}
- pattern = NULL; // make gcc happy
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- color[0] = colToByte(gray);
- pattern = new SplashSolidColor(color);
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- color[0] = colToByte(r);
- color[1] = colToByte(g);
- color[2] = colToByte(b);
- pattern = new SplashSolidColor(color);
- break;
#if SPLASH_CMYK
- case splashModeCMYK8:
- color[0] = colToByte(cmyk->c);
- color[1] = colToByte(cmyk->m);
- color[2] = colToByte(cmyk->y);
- color[3] = colToByte(cmyk->k);
- pattern = new SplashSolidColor(color);
- break;
+SplashPattern *SplashOutputDev::getColor(GfxCMYK *cmyk) {
+ SplashColor color;
+
+ color[0] = colToByte(cmyk->c);
+ color[1] = colToByte(cmyk->m);
+ color[2] = colToByte(cmyk->y);
+ color[3] = colToByte(cmyk->k);
+ return new SplashSolidColor(color);
+}
#endif
- }
- return pattern;
+
+void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace,
+ GBool overprintFlag,
+ int overprintMode,
+ GfxColor *singleColor) {
+#if SPLASH_CMYK
+ Guint mask;
+ GfxCMYK cmyk;
+
+ if (overprintFlag && globalParams->getOverprintPreview()) {
+ mask = colorSpace->getOverprintMask();
+ if (singleColor && overprintMode &&
+ (colorSpace->getMode() == csDeviceCMYK ||
+ (colorSpace->getMode() == csICCBased &&
+ colorSpace->getNComps() == 4))) {
+ colorSpace->getCMYK(singleColor, &cmyk);
+ if (cmyk.c == 0) {
+ mask &= ~1;
+ }
+ if (cmyk.m == 0) {
+ mask &= ~2;
+ }
+ if (cmyk.y == 0) {
+ mask &= ~4;
+ }
+ if (cmyk.k == 0) {
+ mask &= ~8;
+ }
+ }
+ } else {
+ mask = 0xffffffff;
+ }
+ splash->setOverprintMask(mask);
+#endif
}
void SplashOutputDev::updateBlendMode(GfxState *state) {
@@ -956,35 +1013,82 @@ void SplashOutputDev::updateStrokeOpacity(GfxState *state) {
splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
}
+void SplashOutputDev::updateTransfer(GfxState *state) {
+ Function **transfer;
+ Guchar red[256], green[256], blue[256], gray[256];
+ double x, y;
+ int i;
+
+ transfer = state->getTransfer();
+ if (transfer[0] &&
+ transfer[0]->getInputSize() == 1 &&
+ transfer[0]->getOutputSize() == 1) {
+ if (transfer[1] &&
+ transfer[1]->getInputSize() == 1 &&
+ transfer[1]->getOutputSize() == 1 &&
+ transfer[2] &&
+ transfer[2]->getInputSize() == 1 &&
+ transfer[2]->getOutputSize() == 1 &&
+ transfer[3] &&
+ transfer[3]->getInputSize() == 1 &&
+ transfer[3]->getOutputSize() == 1) {
+ for (i = 0; i < 256; ++i) {
+ x = i / 255.0;
+ transfer[0]->transform(&x, &y);
+ red[i] = (Guchar)(y * 255.0 + 0.5);
+ transfer[1]->transform(&x, &y);
+ green[i] = (Guchar)(y * 255.0 + 0.5);
+ transfer[2]->transform(&x, &y);
+ blue[i] = (Guchar)(y * 255.0 + 0.5);
+ transfer[3]->transform(&x, &y);
+ gray[i] = (Guchar)(y * 255.0 + 0.5);
+ }
+ } else {
+ for (i = 0; i < 256; ++i) {
+ x = i / 255.0;
+ transfer[0]->transform(&x, &y);
+ red[i] = green[i] = blue[i] = gray[i] = (Guchar)(y * 255.0 + 0.5);
+ }
+ }
+ } else {
+ for (i = 0; i < 256; ++i) {
+ red[i] = green[i] = blue[i] = gray[i] = (Guchar)i;
+ }
+ }
+ splash->setTransfer(red, green, blue, gray);
+}
+
void SplashOutputDev::updateFont(GfxState *state) {
needFontUpdate = gTrue;
}
void SplashOutputDev::doUpdateFont(GfxState *state) {
GfxFont *gfxFont;
+ GfxFontLoc *fontLoc;
GfxFontType fontType;
SplashOutFontFileID *id;
SplashFontFile *fontFile;
+ int fontNum;
FoFiTrueType *ff;
Ref embRef;
Object refObj, strObj;
- GString *tmpFileName, *fileName, *substName;
+ GString *tmpFileName, *fileName;
FILE *tmpFile;
- Gushort *codeToGID;
- DisplayFontParam *dfp;
+ int *codeToGID;
CharCodeToUnicode *ctu;
double *textMat;
- double m11, m12, m21, m22, w1, w2, fontSize;
+ double m11, m12, m21, m22, fontSize;
+ double w, fontScaleMin, fontScaleAvg, fontScale;
+ Gushort ww;
SplashCoord mat[4];
char *name;
Unicode uBuf[8];
- int c, substIdx, n, code, cmap;
+ int c, substIdx, n, code, cmap, i;
needFontUpdate = gFalse;
font = NULL;
tmpFileName = NULL;
substIdx = -1;
- dfp = NULL;
if (!(gfxFont = state->getFont())) {
goto err1;
@@ -994,6 +1098,13 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
goto err1;
}
+ // sanity-check the font size - skip anything larger than 10 inches
+ // (this avoids problems allocating memory for the font cache)
+ if (state->getTransformedFontSize()
+ > 10 * (state->getHDPI() + state->getVDPI())) {
+ goto err1;
+ }
+
// check the font file cache
id = new SplashOutFontFileID(gfxFont->getID());
if ((fontFile = fontEngine->getFontFile(id))) {
@@ -1001,19 +1112,32 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
} else {
- // if there is an embedded font, write it to disk
- if (gfxFont->getEmbeddedFontID(&embRef)) {
+ fileName = NULL;
+ fontNum = 0;
+
+ if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+ gfxFont->getName() ? gfxFont->getName()->getCString()
+ : "(unnamed)");
+ goto err2;
+ }
+
+ // embedded font
+ if (fontLoc->locType == gfxFontLocEmbedded) {
+ gfxFont->getEmbeddedFontID(&embRef);
if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
- error(-1, "Couldn't create temporary font file");
+ error(errIO, -1, "Couldn't create temporary font file");
+ delete fontLoc;
goto err2;
}
refObj.initRef(embRef.num, embRef.gen);
refObj.fetch(xref, &strObj);
refObj.free();
if (!strObj.isStream()) {
- error(-1, "Embedded font object is wrong type");
+ error(errSyntaxError, -1, "Embedded font object is wrong type");
strObj.free();
fclose(tmpFile);
+ delete fontLoc;
goto err2;
}
strObj.streamReset();
@@ -1025,94 +1149,53 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
fclose(tmpFile);
fileName = tmpFileName;
- // if there is an external font file, use it
- } else if (!(fileName = gfxFont->getExtFontFile())) {
-
- // look for a display font mapping or a substitute font
- if (gfxFont->isCIDFont()) {
- if (((GfxCIDFont *)gfxFont)->getCollection()) {
- dfp = globalParams->
- getDisplayCIDFont(gfxFont->getName(),
- ((GfxCIDFont *)gfxFont)->getCollection());
- }
- } else {
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont->getName());
- }
- if (!dfp) {
- // 8-bit font substitution
- if (gfxFont->isFixedWidth()) {
- substIdx = 8;
- } else if (gfxFont->isSerif()) {
- substIdx = 4;
- } else {
- substIdx = 0;
- }
- if (gfxFont->isBold()) {
- substIdx += 2;
- }
- if (gfxFont->isItalic()) {
- substIdx += 1;
- }
- substName = new GString(splashOutSubstFonts[substIdx].name);
- dfp = globalParams->getDisplayFont(substName);
- delete substName;
- id->setSubstIdx(substIdx);
- }
- }
- if (!dfp) {
- error(-1, "Couldn't find a font for '%s'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- goto err2;
- }
- switch (dfp->kind) {
- case displayFontT1:
- fileName = dfp->t1.fileName;
- fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
- break;
- case displayFontTT:
- fileName = dfp->tt.fileName;
- fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
- break;
+ // external font
+ } else { // gfxFontLocExternal
+ fileName = fontLoc->path;
+ fontNum = fontLoc->fontNum;
+ if (fontLoc->substIdx >= 0) {
+ id->setSubstIdx(fontLoc->substIdx);
}
}
// load the font file
- switch (fontType) {
+ switch (fontLoc->fontType) {
case fontType1:
if (!(fontFile = fontEngine->loadType1Font(
- id,
- fileName->getCString(),
- fileName == tmpFileName,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
+ id,
+ fileName->getCString(),
+ fileName == tmpFileName,
+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
case fontType1C:
if (!(fontFile = fontEngine->loadType1CFont(
- id,
- fileName->getCString(),
- fileName == tmpFileName,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
+ id,
+ fileName->getCString(),
+ fileName == tmpFileName,
+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
case fontType1COT:
if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
- id,
- fileName->getCString(),
- fileName == tmpFileName,
- ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
- error(-1, "Couldn't create a font for '%s'",
+ id,
+ fileName->getCString(),
+ fileName == tmpFileName,
+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
@@ -1122,18 +1205,33 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
n = 256;
delete ff;
+ // if we're substituting for a non-TrueType font, we need to mark
+ // all notdef codes as "do not draw" (rather than drawing TrueType
+ // notdef glyphs)
+ if (gfxFont->getType() != fontTrueType &&
+ gfxFont->getType() != fontTrueTypeOT) {
+ for (i = 0; i < 256; ++i) {
+ if (codeToGID[i] == 0) {
+ codeToGID[i] = -1;
+ }
+ }
+ }
} else {
codeToGID = NULL;
n = 0;
}
if (!(fontFile = fontEngine->loadTrueTypeFont(
id,
- fileName->getCString(),
+ fileName->getCString(), fontNum,
fileName == tmpFileName,
- codeToGID, n))) {
- error(-1, "Couldn't create a font for '%s'",
+ codeToGID, n,
+ gfxFont->getEmbeddedFontName()
+ ? gfxFont->getEmbeddedFontName()->getCString()
+ : (char *)NULL))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
@@ -1143,20 +1241,32 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
id,
fileName->getCString(),
fileName == tmpFileName))) {
- error(-1, "Couldn't create a font for '%s'",
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
case fontCIDType0COT:
+ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+ codeToGID = (int *)gmallocn(n, sizeof(int));
+ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+ n * sizeof(int));
+ } else {
+ codeToGID = NULL;
+ n = 0;
+ }
if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
id,
fileName->getCString(),
- fileName == tmpFileName))) {
- error(-1, "Couldn't create a font for '%s'",
+ fileName == tmpFileName,
+ codeToGID, n))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
@@ -1164,9 +1274,17 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
case fontCIDType2OT:
codeToGID = NULL;
n = 0;
- if (dfp) {
+ if (fontLoc->locType == gfxFontLocEmbedded) {
+ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
+ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+ codeToGID = (int *)gmallocn(n, sizeof(int));
+ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+ n * sizeof(int));
+ }
+ } else {
// create a CID-to-GID mapping, via Unicode
if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
+ //~ this should use fontNum to load the correct font
if ((ff = FoFiTrueType::load(fileName->getCString()))) {
// look for a Unicode cmap
for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
@@ -1179,12 +1297,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
if (cmap < ff->getNumCmaps()) {
// map CID -> Unicode -> GID
n = ctu->getLength();
- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
+ codeToGID = (int *)gmallocn(n, sizeof(int));
for (code = 0; code < n; ++code) {
if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
} else {
- codeToGID[code] = 0;
+ codeToGID[code] = -1;
}
}
}
@@ -1192,26 +1310,24 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
}
ctu->decRefCnt();
} else {
- error(-1, "Couldn't find a mapping to Unicode for font '%s'",
+ error(errSyntaxError, -1,
+ "Couldn't find a mapping to Unicode for font '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
}
- } else {
- if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
- n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
- memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
- n * sizeof(Gushort));
- }
}
if (!(fontFile = fontEngine->loadTrueTypeFont(
id,
- fileName->getCString(),
+ fileName->getCString(), fontNum,
fileName == tmpFileName,
- codeToGID, n))) {
- error(-1, "Couldn't create a font for '%s'",
+ codeToGID, n,
+ gfxFont->getEmbeddedFontName()
+ ? gfxFont->getEmbeddedFontName()->getCString()
+ : (char *)NULL))) {
+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
+ delete fontLoc;
goto err2;
}
break;
@@ -1219,6 +1335,8 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
// this shouldn't happen
goto err2;
}
+
+ delete fontLoc;
}
// get the font matrix
@@ -1230,26 +1348,42 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
m22 = textMat[3] * fontSize;
// for substituted fonts: adjust the font matrix -- compare the
- // width of 'm' in the original font and the substituted font
+ // widths of letters and digits (A-Z, a-z, 0-9) in the original font
+ // and the substituted font
substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx();
- if (substIdx >= 0) {
+ if (substIdx >= 0 && substIdx < 12) {
+ fontScaleMin = 1;
+ fontScaleAvg = 0;
+ n = 0;
for (code = 0; code < 256; ++code) {
if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
- name[0] == 'm' && name[1] == '\0') {
- break;
+ name[0] && !name[1] &&
+ ((name[0] >= 'A' && name[0] <= 'Z') ||
+ (name[0] >= 'a' && name[0] <= 'z') ||
+ (name[0] >= '0' && name[0] <= '9'))) {
+ w = ((Gfx8BitFont *)gfxFont)->getWidth(code);
+ builtinFontSubst[substIdx]->widths->getWidth(name, &ww);
+ if (w > 0.01 && ww > 10) {
+ w /= ww * 0.001;
+ if (w < fontScaleMin) {
+ fontScaleMin = w;
+ }
+ fontScaleAvg += w;
+ ++n;
+ }
}
}
- if (code < 256) {
- w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
- w2 = splashOutSubstFonts[substIdx].mWidth;
- if (!gfxFont->isSymbolic()) {
- // if real font is substantially narrower than substituted
- // font, reduce the font size accordingly
- if (w1 > 0.01 && w1 < 0.9 * w2) {
- w1 /= w2;
- m11 *= w1;
- m21 *= w1;
- }
+ // if real font is narrower than substituted font, reduce the font
+ // size accordingly -- this currently uses a scale factor halfway
+ // between the minimum and average computed scale factors, which
+ // is a bit of a kludge, but seems to produce mostly decent
+ // results
+ if (n) {
+ fontScaleAvg /= n;
+ if (fontScaleAvg < 1) {
+ fontScale = 0.5 * (fontScaleMin + fontScaleAvg);
+ m11 *= fontScale;
+ m12 *= fontScale;
}
}
}
@@ -1280,7 +1414,9 @@ void SplashOutputDev::stroke(GfxState *state) {
if (state->getStrokeColorSpace()->isNonMarking()) {
return;
}
- path = convertPath(state, state->getPath());
+ setOverprintMask(state->getStrokeColorSpace(), state->getStrokeOverprint(),
+ state->getOverprintMode(), state->getStrokeColor());
+ path = convertPath(state, state->getPath(), gFalse);
splash->stroke(path);
delete path;
}
@@ -1291,7 +1427,9 @@ void SplashOutputDev::fill(GfxState *state) {
if (state->getFillColorSpace()->isNonMarking()) {
return;
}
- path = convertPath(state, state->getPath());
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
+ path = convertPath(state, state->getPath(), gTrue);
splash->fill(path, gFalse);
delete path;
}
@@ -1302,15 +1440,155 @@ void SplashOutputDev::eoFill(GfxState *state) {
if (state->getFillColorSpace()->isNonMarking()) {
return;
}
- path = convertPath(state, state->getPath());
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
+ path = convertPath(state, state->getPath(), gTrue);
splash->fill(path, gTrue);
delete path;
}
+void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep) {
+ double tileXMin, tileYMin, tileXMax, tileYMax, tx, ty;
+ int tileX0, tileY0, tileW, tileH, tileSize;
+ SplashBitmap *origBitmap, *tileBitmap;
+ Splash *origSplash;
+ SplashColor color;
+ double mat1[6];
+ double xa, ya, xb, yb, xc, yc;
+ int x, y, xx, yy, i;
+
+ // transform the four corners of the bbox from pattern space to
+ // device space and compute the device space bbox
+ state->transform(bbox[0] * mat[0] + bbox[1] * mat[2] + mat[4],
+ bbox[0] * mat[1] + bbox[1] * mat[3] + mat[5],
+ &tx, &ty);
+ tileXMin = tileXMax = tx;
+ tileYMin = tileYMax = ty;
+ state->transform(bbox[2] * mat[0] + bbox[1] * mat[2] + mat[4],
+ bbox[2] * mat[1] + bbox[1] * mat[3] + mat[5],
+ &tx, &ty);
+ if (tx < tileXMin) {
+ tileXMin = tx;
+ } else if (tx > tileXMax) {
+ tileXMax = tx;
+ }
+ if (ty < tileYMin) {
+ tileYMin = ty;
+ } else if (ty > tileYMax) {
+ tileYMax = ty;
+ }
+ state->transform(bbox[2] * mat[0] + bbox[3] * mat[2] + mat[4],
+ bbox[2] * mat[1] + bbox[3] * mat[3] + mat[5],
+ &tx, &ty);
+ if (tx < tileXMin) {
+ tileXMin = tx;
+ } else if (tx > tileXMax) {
+ tileXMax = tx;
+ }
+ if (ty < tileYMin) {
+ tileYMin = ty;
+ } else if (ty > tileYMax) {
+ tileYMax = ty;
+ }
+ state->transform(bbox[0] * mat[0] + bbox[3] * mat[2] + mat[4],
+ bbox[0] * mat[1] + bbox[3] * mat[3] + mat[5],
+ &tx, &ty);
+ if (tx < tileXMin) {
+ tileXMin = tx;
+ } else if (tx > tileXMax) {
+ tileXMax = tx;
+ }
+ if (ty < tileYMin) {
+ tileYMin = ty;
+ } else if (ty > tileYMax) {
+ tileYMax = ty;
+ }
+ if (tileXMin == tileXMax || tileYMin == tileYMax) {
+ return;
+ }
+
+ tileX0 = (int)floor(tileXMin);
+ tileY0 = (int)floor(tileYMin);
+ tileW = (int)ceil(tileXMax) - tileX0;
+ tileH = (int)ceil(tileYMax) - tileY0;
+
+ // check for an excessively large tile size
+ tileSize = tileW * tileH;
+ if (tileSize > 1000000 || tileSize < 0) {
+ mat1[0] = mat[0];
+ mat1[1] = mat[1];
+ mat1[2] = mat[2];
+ mat1[3] = mat[3];
+ for (y = y0; y < y1; ++y) {
+ for (x = x0; x < x1; ++x) {
+ xa = x * xStep;
+ ya = y * yStep;
+ mat1[4] = xa * mat[0] + ya * mat[2] + mat[4];
+ mat1[5] = xa * mat[1] + ya * mat[3] + mat[5];
+ gfx->drawForm(str, resDict, mat1, bbox);
+ }
+ }
+ return;
+ }
+
+ // create a temporary bitmap
+ origBitmap = bitmap;
+ origSplash = splash;
+ bitmap = tileBitmap = new SplashBitmap(tileW, tileH, bitmapRowPad,
+ colorMode, gTrue, bitmapTopDown);
+ splash = new Splash(bitmap, vectorAntialias, origSplash->getScreen());
+ splash->setMinLineWidth(globalParams->getMinLineWidth());
+ for (i = 0; i < splashMaxColorComps; ++i) {
+ color[i] = 0;
+ }
+ splash->clear(color);
+ ++nestCount;
+
+ // copy the fill color (for uncolored tiling patterns)
+ // (and stroke color, to handle buggy PDF files)
+ splash->setFillPattern(origSplash->getFillPattern()->copy());
+ splash->setStrokePattern(origSplash->getStrokePattern()->copy());
+
+ // render the tile
+ state->shiftCTM(-tileX0, -tileY0);
+ updateCTM(state, 0, 0, 0, 0, 0, 0);
+ gfx->drawForm(str, resDict, mat, bbox);
+ state->shiftCTM(tileX0, tileY0);
+ updateCTM(state, 0, 0, 0, 0, 0, 0);
+
+ // restore the original bitmap
+ --nestCount;
+ delete splash;
+ bitmap = origBitmap;
+ splash = origSplash;
+ splash->setOverprintMask(0xffffffff);
+
+ // draw the tiles
+ for (y = y0; y < y1; ++y) {
+ for (x = x0; x < x1; ++x) {
+ xa = x * xStep;
+ ya = y * yStep;
+ xb = xa * mat[0] + ya * mat[2];
+ yb = xa * mat[1] + ya * mat[3];
+ state->transformDelta(xb, yb, &xc, &yc);
+ xx = (int)(xc + tileX0 + 0.5);
+ yy = (int)(yc + tileY0 + 0.5);
+ splash->composite(tileBitmap, 0, 0, xx, yy, tileW, tileH,
+ gFalse, gFalse);
+ }
+ }
+
+ delete tileBitmap;
+}
+
void SplashOutputDev::clip(GfxState *state) {
SplashPath *path;
- path = convertPath(state, state->getPath());
+ path = convertPath(state, state->getPath(), gTrue);
splash->clipToPath(path, gFalse);
delete path;
}
@@ -1318,7 +1596,7 @@ void SplashOutputDev::clip(GfxState *state) {
void SplashOutputDev::eoClip(GfxState *state) {
SplashPath *path;
- path = convertPath(state, state->getPath());
+ path = convertPath(state, state->getPath(), gTrue);
splash->clipToPath(path, gTrue);
delete path;
}
@@ -1326,22 +1604,24 @@ void SplashOutputDev::eoClip(GfxState *state) {
void SplashOutputDev::clipToStrokePath(GfxState *state) {
SplashPath *path, *path2;
- path = convertPath(state, state->getPath());
- path2 = splash->makeStrokePath(path);
+ path = convertPath(state, state->getPath(), gFalse);
+ path2 = splash->makeStrokePath(path, state->getLineWidth());
delete path;
splash->clipToPath(path2, gFalse);
delete path2;
}
-SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) {
+SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path,
+ GBool dropEmptySubpaths) {
SplashPath *sPath;
GfxSubpath *subpath;
- int i, j;
+ int n, i, j;
+ n = dropEmptySubpaths ? 1 : 0;
sPath = new SplashPath();
for (i = 0; i < path->getNumSubpaths(); ++i) {
subpath = path->getSubpath(i);
- if (subpath->getNumPoints() > 0) {
+ if (subpath->getNumPoints() > n) {
sPath->moveTo((SplashCoord)subpath->getX(0),
(SplashCoord)subpath->getY(0));
j = 1;
@@ -1375,6 +1655,18 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y,
Unicode *u, int uLen) {
SplashPath *path;
int render;
+ GBool doFill, doStroke, doClip, strokeAdjust;
+ double m[4];
+ GBool horiz;
+
+ if (skipHorizText || skipRotatedText) {
+ state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]);
+ horiz = m[0] > 0 && fabs(m[1]) < 0.001 &&
+ fabs(m[2]) < 0.001 && m[3] < 0;
+ if ((skipHorizText && horiz) || (skipRotatedText && !horiz)) {
+ return;
+ }
+ }
// check for invisible text -- this is used by Acrobat Capture
render = state->getRender();
@@ -1392,36 +1684,76 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y,
x -= originX;
y -= originY;
- // fill
- if (!(render & 1)) {
- if (!state->getFillColorSpace()->isNonMarking()) {
- splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
+ doFill = !(render & 1) && !state->getFillColorSpace()->isNonMarking();
+ doStroke = ((render & 3) == 1 || (render & 3) == 2) &&
+ !state->getStrokeColorSpace()->isNonMarking();
+ doClip = render & 4;
+
+ path = NULL;
+ if (doStroke || doClip) {
+ if ((path = font->getGlyphPath(code))) {
+ path->offset((SplashCoord)x, (SplashCoord)y);
}
}
+ // don't use stroke adjustment when stroking text -- the results
+ // tend to be ugly (because characters with horizontal upper or
+ // lower edges get misaligned relative to the other characters)
+ strokeAdjust = gFalse; // make gcc happy
+ if (doStroke) {
+ strokeAdjust = splash->getStrokeAdjust();
+ splash->setStrokeAdjust(gFalse);
+ }
+
+ // fill and stroke
+ if (doFill && doStroke) {
+ if (path) {
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
+ splash->fill(path, gFalse);
+ setOverprintMask(state->getStrokeColorSpace(),
+ state->getStrokeOverprint(),
+ state->getOverprintMode(),
+ state->getStrokeColor());
+ splash->stroke(path);
+ }
+
+ // fill
+ } else if (doFill) {
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
+ splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
+
// stroke
- if ((render & 3) == 1 || (render & 3) == 2) {
- if (!state->getStrokeColorSpace()->isNonMarking()) {
- if ((path = font->getGlyphPath(code))) {
- path->offset((SplashCoord)x, (SplashCoord)y);
- splash->stroke(path);
- delete path;
- }
+ } else if (doStroke) {
+ if (path) {
+ setOverprintMask(state->getStrokeColorSpace(),
+ state->getStrokeOverprint(),
+ state->getOverprintMode(),
+ state->getStrokeColor());
+ splash->stroke(path);
}
}
// clip
- if (render & 4) {
- if ((path = font->getGlyphPath(code))) {
- path->offset((SplashCoord)x, (SplashCoord)y);
+ if (doClip) {
+ if (path) {
if (textClipPath) {
textClipPath->append(path);
- delete path;
} else {
textClipPath = path;
+ path = NULL;
}
}
}
+
+ if (doStroke) {
+ splash->setStrokeAdjust(strokeAdjust);
+ }
+
+ if (path) {
+ delete path;
+ }
}
GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
@@ -1433,9 +1765,20 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
T3FontCache *t3Font;
T3GlyphStack *t3gs;
GBool validBBox;
+ double m[4];
+ GBool horiz;
double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
int i, j;
+ if (skipHorizText || skipRotatedText) {
+ state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]);
+ horiz = m[0] > 0 && fabs(m[1]) < 0.001 &&
+ fabs(m[2]) < 0.001 && m[3] < 0;
+ if ((skipHorizText && horiz) || (skipRotatedText && !horiz)) {
+ return gTrue;
+ }
+ }
+
if (!(gfxFont = state->getFont())) {
return gFalse;
}
@@ -1517,10 +1860,10 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
validBBox = gTrue;
}
t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
- (int)floor(xMin - xt),
- (int)floor(yMin - yt),
- (int)ceil(xMax) - (int)floor(xMin) + 3,
- (int)ceil(yMax) - (int)floor(yMin) + 3,
+ (int)floor(xMin - xt) - 2,
+ (int)floor(yMin - yt) - 2,
+ (int)ceil(xMax) - (int)floor(xMin) + 4,
+ (int)ceil(yMax) - (int)floor(yMin) + 4,
validBBox,
colorMode != splashModeMono1);
}
@@ -1532,7 +1875,7 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
for (j = 0; j < t3Font->cacheAssoc; ++j) {
if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
t3Font->cacheTags[i+j].code == code) {
- drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
+ drawType3Glyph(state, t3Font, &t3Font->cacheTags[i+j],
t3Font->cacheData + (i+j) * t3Font->glyphSize);
return gTrue;
}
@@ -1547,6 +1890,8 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
t3GlyphStack->cacheTag = NULL;
t3GlyphStack->cacheData = NULL;
+ haveT3Dx = gFalse;
+
return gFalse;
}
@@ -1555,6 +1900,7 @@ void SplashOutputDev::endType3Char(GfxState *state) {
double *ctm;
if (t3GlyphStack->cacheTag) {
+ --nestCount;
memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(),
t3GlyphStack->cache->glyphSize);
delete bitmap;
@@ -1565,7 +1911,7 @@ void SplashOutputDev::endType3Char(GfxState *state) {
state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
updateCTM(state, 0, 0, 0, 0, 0, 0);
- drawType3Glyph(t3GlyphStack->cache,
+ drawType3Glyph(state, t3GlyphStack->cache,
t3GlyphStack->cacheTag, t3GlyphStack->cacheData);
}
t3gs = t3GlyphStack;
@@ -1574,6 +1920,7 @@ void SplashOutputDev::endType3Char(GfxState *state) {
}
void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) {
+ haveT3Dx = gTrue;
}
void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
@@ -1584,6 +1931,12 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
int i, j;
+ // ignore multiple d0/d1 operators
+ if (haveT3Dx) {
+ return;
+ }
+ haveT3Dx = gTrue;
+
t3Font = t3GlyphStack->cache;
// check for a valid bbox
@@ -1629,7 +1982,7 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
xMax - xt > t3Font->glyphX + t3Font->glyphW ||
yMax - yt > t3Font->glyphY + t3Font->glyphH) {
if (t3Font->validBBox) {
- error(-1, "Bad bounding box in Type 3 glyph");
+ error(errSyntaxWarning, -1, "Bad bounding box in Type 3 glyph");
}
return;
}
@@ -1662,7 +2015,7 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
t3GlyphStack->origSplash->getScreen());
color[0] = 0;
splash->clear(color);
- color[0] = 1;
+ color[0] = 0xff;
} else {
bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
splashModeMono8, gFalse);
@@ -1672,18 +2025,23 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
splash->clear(color);
color[0] = 0xff;
}
+ splash->setMinLineWidth(globalParams->getMinLineWidth());
splash->setFillPattern(new SplashSolidColor(color));
splash->setStrokePattern(new SplashSolidColor(color));
//~ this should copy other state from t3GlyphStack->origSplash?
+ //~ [this is likely the same situation as in beginTransparencyGroup()]
state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
-t3Font->glyphX, -t3Font->glyphY);
updateCTM(state, 0, 0, 0, 0, 0, 0);
+ ++nestCount;
}
-void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
+void SplashOutputDev::drawType3Glyph(GfxState *state, T3FontCache *t3Font,
T3FontCacheTag *tag, Guchar *data) {
SplashGlyphBitmap glyph;
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
glyph.x = -t3Font->glyphX;
glyph.y = -t3Font->glyphY;
glyph.w = t3Font->glyphW;
@@ -1717,9 +2075,10 @@ GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) {
if (imgMaskData->y == imgMaskData->height) {
return gFalse;
}
- for (x = 0, p = imgMaskData->imgStr->getLine(), q = line;
- x < imgMaskData->width;
- ++x) {
+ if (!(p = imgMaskData->imgStr->getLine())) {
+ return gFalse;
+ }
+ for (x = 0, q = line; x < imgMaskData->width; ++x) {
*q++ = *p++ ^ imgMaskData->invert;
}
++imgMaskData->y;
@@ -1736,6 +2095,8 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
if (state->getFillColorSpace()->isNonMarking()) {
return;
}
+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), state->getFillColor());
ctm = state->getCTM();
mat[0] = ctm[0];
@@ -1765,6 +2126,46 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
str->close();
}
+void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state,
+ Object *ref, Stream *str,
+ int width, int height,
+ GBool invert,
+ GBool inlineImg) {
+ double *ctm;
+ SplashCoord mat[6];
+ SplashOutImageMaskData imgMaskData;
+ SplashBitmap *maskBitmap;
+ Splash *maskSplash;
+ SplashColor maskColor;
+
+ ctm = state->getCTM();
+ mat[0] = ctm[0];
+ mat[1] = ctm[1];
+ mat[2] = -ctm[2];
+ mat[3] = -ctm[3];
+ mat[4] = ctm[2] + ctm[4];
+ mat[5] = ctm[3] + ctm[5];
+ imgMaskData.imgStr = new ImageStream(str, width, 1, 1);
+ imgMaskData.imgStr->reset();
+ imgMaskData.invert = invert ? 0 : 1;
+ imgMaskData.width = width;
+ imgMaskData.height = height;
+ imgMaskData.y = 0;
+ maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
+ 1, splashModeMono8, gFalse);
+ maskSplash = new Splash(maskBitmap, gTrue);
+ maskColor[0] = 0;
+ maskSplash->clear(maskColor);
+ maskColor[0] = 0xff;
+ maskSplash->setFillPattern(new SplashSolidColor(maskColor));
+ maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
+ width, height, mat, gFalse);
+ delete imgMaskData.imgStr;
+ str->close();
+ delete maskSplash;
+ splash->setSoftMask(maskBitmap);
+}
+
struct SplashOutImageData {
ImageStream *imgStr;
GfxImageColorMap *colorMap;
@@ -1789,6 +2190,9 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
if (imgData->y == imgData->height) {
return gFalse;
}
+ if (!(p = imgData->imgStr->getLine())) {
+ return gFalse;
+ }
nComps = imgData->colorMap->getNumPixelComps();
@@ -1796,17 +2200,13 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
switch (imgData->colorMode) {
case splashModeMono1:
case splashModeMono8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
*q++ = imgData->lookup[*p];
}
break;
case splashModeRGB8:
case splashModeBGR8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
col = &imgData->lookup[3 * *p];
*q++ = col[0];
*q++ = col[1];
@@ -1815,9 +2215,7 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, ++p) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
col = &imgData->lookup[4 * *p];
*q++ = col[0];
*q++ = col[1];
@@ -1831,18 +2229,14 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
switch (imgData->colorMode) {
case splashModeMono1:
case splashModeMono8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
imgData->colorMap->getGray(p, &gray);
*q++ = colToByte(gray);
}
break;
case splashModeRGB8:
case splashModeBGR8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
imgData->colorMap->getRGB(p, &rgb);
*q++ = colToByte(rgb.r);
*q++ = colToByte(rgb.g);
@@ -1851,9 +2245,7 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
- x < imgData->width;
- ++x, p += nComps) {
+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
imgData->colorMap->getCMYK(p, &cmyk);
*q++ = colToByte(cmyk.c);
*q++ = colToByte(cmyk.m);
@@ -1885,10 +2277,13 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
if (imgData->y == imgData->height) {
return gFalse;
}
+ if (!(p = imgData->imgStr->getLine())) {
+ return gFalse;
+ }
nComps = imgData->colorMap->getNumPixelComps();
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
+ for (x = 0, q = colorLine, aq = alphaLine;
x < imgData->width;
++x, p += nComps) {
alpha = 0;
@@ -1904,7 +2299,6 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
case splashModeMono1:
case splashModeMono8:
*q++ = imgData->lookup[*p];
- *aq++ = alpha;
break;
case splashModeRGB8:
case splashModeBGR8:
@@ -1912,7 +2306,6 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
*q++ = col[0];
*q++ = col[1];
*q++ = col[2];
- *aq++ = alpha;
break;
#if SPLASH_CMYK
case splashModeCMYK8:
@@ -1921,17 +2314,16 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
*q++ = col[1];
*q++ = col[2];
*q++ = col[3];
- *aq++ = alpha;
break;
#endif
}
+ *aq++ = alpha;
} else {
switch (imgData->colorMode) {
case splashModeMono1:
case splashModeMono8:
imgData->colorMap->getGray(p, &gray);
*q++ = colToByte(gray);
- *aq++ = alpha;
break;
case splashModeRGB8:
case splashModeBGR8:
@@ -1939,7 +2331,6 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
*q++ = colToByte(rgb.r);
*q++ = colToByte(rgb.g);
*q++ = colToByte(rgb.b);
- *aq++ = alpha;
break;
#if SPLASH_CMYK
case splashModeCMYK8:
@@ -1948,10 +2339,10 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
*q++ = colToByte(cmyk.m);
*q++ = colToByte(cmyk.y);
*q++ = colToByte(cmyk.k);
- *aq++ = alpha;
break;
#endif
}
+ *aq++ = alpha;
}
}
@@ -1976,6 +2367,9 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
Guchar pix;
int n, i;
+ setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), NULL);
+
ctm = state->getCTM();
mat[0] = ctm[0];
mat[1] = ctm[1];
@@ -2012,7 +2406,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
break;
case splashModeRGB8:
case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 3);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getRGB(&pix, &rgb);
@@ -2023,7 +2417,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getCMYK(&pix, &cmyk);
@@ -2034,7 +2428,6 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
}
break;
#endif
- break;
}
}
@@ -2071,7 +2464,6 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
Guchar *alphaLine) {
SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data;
Guchar *p, *aq;
- SplashColor maskColor;
SplashColorPtr q, col;
GfxRGB rgb;
GfxGray gray;
@@ -2079,25 +2471,35 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
GfxCMYK cmyk;
#endif
Guchar alpha;
+ Guchar *maskPtr;
+ int maskBit;
int nComps, x;
if (imgData->y == imgData->height) {
return gFalse;
}
+ if (!(p = imgData->imgStr->getLine())) {
+ return gFalse;
+ }
nComps = imgData->colorMap->getNumPixelComps();
- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
+ maskPtr = imgData->mask->getDataPtr() +
+ imgData->y * imgData->mask->getRowSize();
+ maskBit = 0x80;
+ for (x = 0, q = colorLine, aq = alphaLine;
x < imgData->width;
++x, p += nComps) {
- imgData->mask->getPixel(x, imgData->y, maskColor);
- alpha = maskColor[0] ? 0xff : 0x00;
+ alpha = (*maskPtr & maskBit) ? 0xff : 0x00;
+ if (!(maskBit >>= 1)) {
+ ++maskPtr;
+ maskBit = 0x80;
+ }
if (imgData->lookup) {
switch (imgData->colorMode) {
case splashModeMono1:
case splashModeMono8:
*q++ = imgData->lookup[*p];
- *aq++ = alpha;
break;
case splashModeRGB8:
case splashModeBGR8:
@@ -2105,7 +2507,6 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
*q++ = col[0];
*q++ = col[1];
*q++ = col[2];
- *aq++ = alpha;
break;
#if SPLASH_CMYK
case splashModeCMYK8:
@@ -2114,17 +2515,16 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
*q++ = col[1];
*q++ = col[2];
*q++ = col[3];
- *aq++ = alpha;
break;
#endif
}
+ *aq++ = alpha;
} else {
switch (imgData->colorMode) {
case splashModeMono1:
case splashModeMono8:
imgData->colorMap->getGray(p, &gray);
*q++ = colToByte(gray);
- *aq++ = alpha;
break;
case splashModeRGB8:
case splashModeBGR8:
@@ -2132,7 +2532,6 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
*q++ = colToByte(rgb.r);
*q++ = colToByte(rgb.g);
*q++ = colToByte(rgb.b);
- *aq++ = alpha;
break;
#if SPLASH_CMYK
case splashModeCMYK8:
@@ -2141,10 +2540,10 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
*q++ = colToByte(cmyk.m);
*q++ = colToByte(cmyk.y);
*q++ = colToByte(cmyk.k);
- *aq++ = alpha;
break;
#endif
}
+ *aq++ = alpha;
}
}
@@ -2175,6 +2574,9 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
Guchar pix;
int n, i;
+ setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), NULL);
+
// If the mask is higher resolution than the image, use
// drawSoftMaskedImage() instead.
if (maskWidth > width || maskHeight > height) {
@@ -2256,7 +2658,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
break;
case splashModeRGB8:
case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 3);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getRGB(&pix, &rgb);
@@ -2267,7 +2669,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getCMYK(&pix, &cmyk);
@@ -2318,6 +2720,9 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
Guchar pix;
int n, i;
+ setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
+ state->getOverprintMode(), NULL);
+
ctm = state->getCTM();
mat[0] = ctm[0];
mat[1] = ctm[1];
@@ -2388,7 +2793,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
break;
case splashModeRGB8:
case splashModeBGR8:
- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 3);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getRGB(&pix, &rgb);
@@ -2399,7 +2804,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
+ imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getCMYK(&pix, &cmyk);
@@ -2433,7 +2838,7 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
SplashTransparencyGroup *transpGroup;
SplashColor color;
double xMin, yMin, xMax, yMax, x, y;
- int tx, ty, w, h;
+ int tx, ty, w, h, i;
// transform the bbox
state->transform(bbox[0], bbox[1], &x, &y);
@@ -2475,14 +2880,14 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
tx = (int)floor(xMin);
if (tx < 0) {
tx = 0;
- } else if (tx > bitmap->getWidth()) {
- tx = bitmap->getWidth();
+ } else if (tx >= bitmap->getWidth()) {
+ tx = bitmap->getWidth() - 1;
}
ty = (int)floor(yMin);
if (ty < 0) {
ty = 0;
- } else if (ty > bitmap->getHeight()) {
- ty = bitmap->getHeight();
+ } else if (ty >= bitmap->getHeight()) {
+ ty = bitmap->getHeight() - 1;
}
w = (int)ceil(xMax) - tx + 1;
if (tx + w > bitmap->getWidth()) {
@@ -2512,31 +2917,47 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
transpGroup->origBitmap = bitmap;
transpGroup->origSplash = splash;
- //~ this ignores the blendingColorSpace arg
+ //~ this handles the blendingColorSpace arg for soft masks, but
+ //~ not yet for transparency groups
+
+ // switch to the blending color space
+ if (forSoftMask && isolated && blendingColorSpace) {
+ if (blendingColorSpace->getMode() == csDeviceGray ||
+ blendingColorSpace->getMode() == csCalGray ||
+ (blendingColorSpace->getMode() == csICCBased &&
+ blendingColorSpace->getNComps() == 1)) {
+ colorMode = splashModeMono8;
+ } else if (blendingColorSpace->getMode() == csDeviceRGB ||
+ blendingColorSpace->getMode() == csCalRGB ||
+ (blendingColorSpace->getMode() == csICCBased &&
+ blendingColorSpace->getNComps() == 3)) {
+ //~ does this need to use BGR8?
+ colorMode = splashModeRGB8;
+#if SPLASH_CMYK
+ } else if (blendingColorSpace->getMode() == csDeviceCMYK ||
+ (blendingColorSpace->getMode() == csICCBased &&
+ blendingColorSpace->getNComps() == 4)) {
+ colorMode = splashModeCMYK8;
+#endif
+ }
+ }
// create the temporary bitmap
bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
bitmapTopDown);
splash = new Splash(bitmap, vectorAntialias,
transpGroup->origSplash->getScreen());
+ splash->setMinLineWidth(globalParams->getMinLineWidth());
+ //~ Acrobat apparently copies at least the fill and stroke colors, and
+ //~ maybe other state(?) -- but not the clipping path (and not sure
+ //~ what else)
+ //~ [this is likely the same situation as in type3D1()]
+ splash->setFillPattern(transpGroup->origSplash->getFillPattern()->copy());
+ splash->setStrokePattern(
+ transpGroup->origSplash->getStrokePattern()->copy());
if (isolated) {
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- color[0] = 0;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- color[0] = color[1] = color[2] = 0;
- break;
-#if SPLASH_CMYK
- case splashModeCMYK8:
- color[0] = color[1] = color[2] = color[3] = 0;
- break;
-#endif
- default:
- // make gcc happy
- break;
+ for (i = 0; i < splashMaxColorComps; ++i) {
+ color[i] = 0;
}
splash->clear(color, 0);
} else {
@@ -2546,16 +2967,16 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
transpGroup->tBitmap = bitmap;
state->shiftCTM(-tx, -ty);
updateCTM(state, 0, 0, 0, 0, 0, 0);
+ ++nestCount;
}
void SplashOutputDev::endTransparencyGroup(GfxState *state) {
- double *ctm;
-
// restore state
+ --nestCount;
delete splash;
bitmap = transpGroupStack->origBitmap;
+ colorMode = bitmap->getMode();
splash = transpGroupStack->origSplash;
- ctm = state->getCTM();
state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty);
updateCTM(state, 0, 0, 0, 0, 0, 0);
}
@@ -2573,9 +2994,12 @@ void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) {
// paint the transparency group onto the parent bitmap
// - the clip path was set in the parent's state)
- splash->composite(tBitmap, 0, 0, tx, ty,
- tBitmap->getWidth(), tBitmap->getHeight(),
- gFalse, !isolated);
+ if (tx < bitmap->getWidth() && ty < bitmap->getHeight()) {
+ splash->setOverprintMask(0xffffffff);
+ splash->composite(tBitmap, 0, 0, tx, ty,
+ tBitmap->getWidth(), tBitmap->getHeight(),
+ gFalse, !isolated);
+ }
// pop the stack
transpGroup = transpGroupStack;
@@ -2606,13 +3030,13 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox,
tBitmap = transpGroupStack->tBitmap;
// composite with backdrop color
- if (!alpha && colorMode != splashModeMono1) {
+ if (!alpha && tBitmap->getMode() != splashModeMono1) {
//~ need to correctly handle the case where no blending color
//~ space is given
tSplash = new Splash(tBitmap, vectorAntialias,
transpGroupStack->origSplash->getScreen());
if (transpGroupStack->blendingColorSpace) {
- switch (colorMode) {
+ switch (tBitmap->getMode()) {
case splashModeMono1:
// transparency is not supported in mono1 mode
break;
@@ -2648,36 +3072,38 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox,
1, splashModeMono8, gFalse);
memset(softMask->getDataPtr(), 0,
softMask->getRowSize() * softMask->getHeight());
- p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
- for (y = 0; y < tBitmap->getHeight(); ++y) {
- for (x = 0; x < tBitmap->getWidth(); ++x) {
- tBitmap->getPixel(x, y, color);
- if (alpha) {
- //~ unimplemented
- } else {
- // convert to luminosity
- switch (colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- lum = color[0] / 255.0;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
- lum = (0.3 / 255.0) * color[0] +
- (0.59 / 255.0) * color[1] +
- (0.11 / 255.0) * color[2];
- break;
+ if (tx < softMask->getWidth() && ty < softMask->getHeight()) {
+ p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
+ for (y = 0; y < tBitmap->getHeight(); ++y) {
+ for (x = 0; x < tBitmap->getWidth(); ++x) {
+ if (alpha) {
+ lum = tBitmap->getAlpha(x, y) / 255.0;
+ } else {
+ tBitmap->getPixel(x, y, color);
+ // convert to luminosity
+ switch (tBitmap->getMode()) {
+ case splashModeMono1:
+ case splashModeMono8:
+ lum = color[0] / 255.0;
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ lum = (0.3 / 255.0) * color[0] +
+ (0.59 / 255.0) * color[1] +
+ (0.11 / 255.0) * color[2];
+ break;
#if SPLASH_CMYK
- case splashModeCMYK8:
- lum = (1 - color[4] / 255.0)
- - (0.3 / 255.0) * color[0]
- - (0.59 / 255.0) * color[1]
- - (0.11 / 255.0) * color[2];
- if (lum < 0) {
- lum = 0;
- }
- break;
+ case splashModeCMYK8:
+ lum = (1 - color[3] / 255.0)
+ - (0.3 / 255.0) * color[0]
+ - (0.59 / 255.0) * color[1]
+ - (0.11 / 255.0) * color[2];
+ if (lum < 0) {
+ lum = 0;
+ }
+ break;
#endif
+ }
}
if (transferFunc) {
transferFunc->transform(&lum, &lum2);
@@ -2686,8 +3112,8 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox,
}
p[x] = (int)(lum2 * 255.0 + 0.5);
}
+ p += softMask->getRowSize();
}
- p += softMask->getRowSize();
}
splash->setSoftMask(softMask);
@@ -2743,39 +3169,49 @@ void SplashOutputDev::setFillColor(int r, int g, int b) {
rgb.r = byteToCol(r);
rgb.g = byteToCol(g);
rgb.b = byteToCol(b);
- gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
- if (gray > gfxColorComp1) {
- gray = gfxColorComp1;
- }
+ switch (colorMode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
+ if (gray > gfxColorComp1) {
+ gray = gfxColorComp1;
+ }
+ splash->setFillPattern(getColor(gray));
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ splash->setFillPattern(getColor(&rgb));
+ break;
#if SPLASH_CMYK
- cmyk.c = gfxColorComp1 - rgb.r;
- cmyk.m = gfxColorComp1 - rgb.g;
- cmyk.y = gfxColorComp1 - rgb.b;
- cmyk.k = 0;
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setFillPattern(getColor(gray, &rgb));
+ case splashModeCMYK8:
+ cmyk.c = gfxColorComp1 - rgb.r;
+ cmyk.m = gfxColorComp1 - rgb.g;
+ cmyk.y = gfxColorComp1 - rgb.b;
+ cmyk.k = 0;
+ splash->setFillPattern(getColor(&cmyk));
+ break;
#endif
+ }
}
-SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
- DisplayFontParam *dfp;
+SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) {
Ref ref;
SplashOutFontFileID *id;
+ GfxFontLoc *fontLoc;
SplashFontFile *fontFile;
SplashFont *fontObj;
FoFiTrueType *ff;
- Gushort *codeToGID;
+ int *codeToGID;
Unicode u;
SplashCoord textMat[4];
int cmap, i;
- for (i = 0; i < 16; ++i) {
- if (!name->cmp(splashOutSubstFonts[i].name)) {
+ for (i = 0; i < nBuiltinFonts; ++i) {
+ if (!name->cmp(builtinFonts[i].name)) {
break;
}
}
- if (i == 16) {
+ if (i == nBuiltinFonts) {
return NULL;
}
ref.num = i;
@@ -2788,12 +3224,16 @@ SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
// load the font file
} else {
- dfp = globalParams->getDisplayFont(name);
- if (dfp && dfp->kind == displayFontT1) {
- fontFile = fontEngine->loadType1Font(id, dfp->t1.fileName->getCString(),
+ if (!(fontLoc = GfxFont::locateBase14Font(name))) {
+ return NULL;
+ }
+ if (fontLoc->fontType == fontType1) {
+ fontFile = fontEngine->loadType1Font(id, fontLoc->path->getCString(),
gFalse, winAnsiEncoding);
- } else if (dfp && dfp->kind == displayFontTT) {
- if (!(ff = FoFiTrueType::load(dfp->tt.fileName->getCString()))) {
+ } else if (fontLoc->fontType == fontTrueType) {
+ if (!(ff = FoFiTrueType::load(fontLoc->path->getCString()))) {
+ delete fontLoc;
+ delete id;
return NULL;
}
for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
@@ -2805,9 +3245,11 @@ SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
}
if (cmap == ff->getNumCmaps()) {
delete ff;
+ delete fontLoc;
+ delete id;
return NULL;
}
- codeToGID = (Gushort *)gmallocn(256, sizeof(Gushort));
+ codeToGID = (int *)gmallocn(256, sizeof(int));
for (i = 0; i < 256; ++i) {
codeToGID[i] = 0;
if (winAnsiEncoding[i] &&
@@ -2817,11 +3259,18 @@ SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
}
delete ff;
fontFile = fontEngine->loadTrueTypeFont(id,
- dfp->tt.fileName->getCString(),
- gFalse, codeToGID, 256);
+ fontLoc->path->getCString(),
+ fontLoc->fontNum,
+ gFalse, codeToGID, 256, NULL);
} else {
+ delete fontLoc;
+ delete id;
return NULL;
}
+ delete fontLoc;
+ }
+ if (!fontFile) {
+ return NULL;
}
// create the scaled font
@@ -2835,11 +3284,7 @@ SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
}
#if 1 //~tmp: turn off anti-aliasing temporarily
-GBool SplashOutputDev::getVectorAntialias() {
- return splash->getVectorAntialias();
-}
-
-void SplashOutputDev::setVectorAntialias(GBool vaa) {
- splash->setVectorAntialias(vaa);
+void SplashOutputDev::setInShading(GBool sh) {
+ splash->setInShading(sh);
}
#endif
diff --git a/xpdf/SplashOutputDev.h b/xpdf/SplashOutputDev.h
index 96f270a..c48b786 100644
--- a/xpdf/SplashOutputDev.h
+++ b/xpdf/SplashOutputDev.h
@@ -58,15 +58,21 @@ public:
// Does this device use upside-down coordinates?
// (Upside-down means (0,0) is the top left corner of the page.)
- virtual GBool upsideDown() { return gTrue; }
+ virtual GBool upsideDown() { return bitmapTopDown ^ bitmapUpsideDown; }
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gTrue; }
+ // Does this device use tilingPatternFill()? If this returns false,
+ // tiling pattern fills will be reduced to a series of other drawing
+ // operations.
+ virtual GBool useTilingPatternFill() { return gTrue; }
+
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
+
//----- initialization and control
// Start a page.
@@ -95,6 +101,7 @@ public:
virtual void updateBlendMode(GfxState *state);
virtual void updateFillOpacity(GfxState *state);
virtual void updateStrokeOpacity(GfxState *state);
+ virtual void updateTransfer(GfxState *state);
//----- update text state
virtual void updateFont(GfxState *state);
@@ -103,6 +110,11 @@ public:
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
+ virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str,
+ int paintType, Dict *resDict,
+ double *mat, double *bbox,
+ int x0, int y0, int x1, int y1,
+ double xStep, double yStep);
//----- path clipping
virtual void clip(GfxState *state);
@@ -124,6 +136,10 @@ public:
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
+ virtual void setSoftMaskFromImageMask(GfxState *state,
+ Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg);
virtual void drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
@@ -174,6 +190,10 @@ public:
// caller.
SplashBitmap *takeBitmap();
+ // Set this flag to true to generate an upside-down bitmap (useful
+ // for Windows BMP files).
+ void setBitmapUpsideDown(GBool f) { bitmapUpsideDown = f; }
+
// Get the Splash object.
Splash *getSplash() { return splash; }
@@ -187,26 +207,36 @@ public:
void setFillColor(int r, int g, int b);
// Get a font object for a Base-14 font, using the Latin-1 encoding.
- SplashFont *getFont(GString *name, double *textMatA);
+ SplashFont *getFont(GString *name, SplashCoord *textMatA);
SplashFont *getCurrentFont() { return font; }
+ // If <skipTextA> is true, don't draw horizontal text.
+ // If <skipRotatedTextA> is true, don't draw rotated (non-horizontal) text.
+ void setSkipText(GBool skipHorizTextA, GBool skipRotatedTextA)
+ { skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; }
+
+ int getNestCount() { return nestCount; }
+
+
#if 1 //~tmp: turn off anti-aliasing temporarily
- virtual GBool getVectorAntialias();
- virtual void setVectorAntialias(GBool vaa);
+ virtual void setInShading(GBool sh);
#endif
private:
void setupScreenParams(double hDPI, double vDPI);
+ SplashPattern *getColor(GfxGray gray);
+ SplashPattern *getColor(GfxRGB *rgb);
#if SPLASH_CMYK
- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk);
-#else
- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
+ SplashPattern *getColor(GfxCMYK *cmyk);
#endif
- SplashPath *convertPath(GfxState *state, GfxPath *path);
+ void setOverprintMask(GfxColorSpace *colorSpace, GBool overprintFlag,
+ int overprintMode, GfxColor *singleColor);
+ SplashPath *convertPath(GfxState *state, GfxPath *path,
+ GBool dropEmptySubpaths);
void doUpdateFont(GfxState *state);
- void drawType3Glyph(T3FontCache *t3Font,
+ void drawType3Glyph(GfxState *state, T3FontCache *t3Font,
T3FontCacheTag *tag, Guchar *data);
static GBool imageMaskSrc(void *data, SplashColorPtr line);
static GBool imageSrc(void *data, SplashColorPtr colorLine,
@@ -219,11 +249,14 @@ private:
SplashColorMode colorMode;
int bitmapRowPad;
GBool bitmapTopDown;
+ GBool bitmapUpsideDown;
GBool allowAntialias;
GBool vectorAntialias;
GBool reverseVideo; // reverse video mode
SplashColor paperColor; // paper color
SplashScreenParams screenParams;
+ GBool skipHorizText;
+ GBool skipRotatedText;
XRef *xref; // xref table for current document
@@ -235,6 +268,7 @@ private:
t3FontCache[splashOutT3FontCacheSize];
int nT3Fonts; // number of valid entries in t3FontCache
T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack
+ GBool haveT3Dx; // set after seeing a d0/d1 operator
SplashFont *font; // current font
GBool needFontUpdate; // set when the font needs to be updated
@@ -242,6 +276,8 @@ private:
SplashTransparencyGroup * // transparency group stack
transpGroupStack;
+
+ int nestCount;
};
#endif
diff --git a/xpdf/Stream-CCITT.h b/xpdf/Stream-CCITT.h
index c4458fe..f82150a 100644
--- a/xpdf/Stream-CCITT.h
+++ b/xpdf/Stream-CCITT.h
@@ -8,6 +8,9 @@
//
//========================================================================
+#ifndef STREAM_CCITT_H
+#define STREAM_CCITT_H
+
struct CCITTCode {
short bits;
short n;
@@ -457,3 +460,5 @@ static CCITTCode blackTab3[64] = {
{2, 2}, {2, 2}, {2, 2}, {2, 2},
{2, 2}, {2, 2}, {2, 2}, {2, 2}
};
+
+#endif
diff --git a/xpdf/Stream.cc b/xpdf/Stream.cc
index 68abafa..d91b941 100644
--- a/xpdf/Stream.cc
+++ b/xpdf/Stream.cc
@@ -60,15 +60,28 @@ void Stream::close() {
}
int Stream::getRawChar() {
- error(-1, "Internal: called getRawChar() on non-predictor stream");
+ error(errInternal, -1, "Called getRawChar() on non-predictor stream");
return EOF;
}
+int Stream::getBlock(char *buf, int size) {
+ int n, c;
+
+ n = 0;
+ while (n < size) {
+ if ((c = getChar()) == EOF) {
+ break;
+ }
+ buf[n++] = (char)c;
+ }
+ return n;
+}
+
char *Stream::getLine(char *buf, int size) {
int i;
int c;
- if (lookChar() == EOF)
+ if (lookChar() == EOF || size < 0)
return NULL;
for (i = 0; i < size - 1; ++i) {
c = getChar();
@@ -85,7 +98,7 @@ char *Stream::getLine(char *buf, int size) {
return buf;
}
-GString *Stream::getPSFilter(int psLevel, char *indent) {
+GString *Stream::getPSFilter(int psLevel, const char *indent) {
return new GString();
}
@@ -118,14 +131,14 @@ Stream *Stream::addFilters(Object *dict) {
if (obj2.isName()) {
str = makeFilter(obj2.getName(), str, &params2);
} else {
- error(getPos(), "Bad filter name");
+ error(errSyntaxError, getPos(), "Bad filter name");
str = new EOFStream(str);
}
obj2.free();
params2.free();
}
} else if (!obj.isNull()) {
- error(getPos(), "Bad 'Filter' attribute in stream");
+ error(errSyntaxError, getPos(), "Bad 'Filter' attribute in stream");
}
obj.free();
params.free();
@@ -268,7 +281,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
} else if (!strcmp(name, "JPXDecode")) {
str = new JPXStream(str);
} else {
- error(getPos(), "Unknown filter '%s'", name);
+ error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
str = new EOFStream(str);
}
return str;
@@ -302,7 +315,7 @@ void FilterStream::close() {
}
void FilterStream::setPos(Guint pos, int dir) {
- error(-1, "Internal: called setPos() on FilterStream");
+ error(errInternal, -1, "Called setPos() on FilterStream");
}
//------------------------------------------------------------------------
@@ -318,17 +331,34 @@ ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
nBits = nBitsA;
nVals = width * nComps;
- if (nBits == 1) {
- imgLineSize = (nVals + 7) & ~7;
+ inputLineSize = (nVals * nBits + 7) >> 3;
+ if (nVals > INT_MAX / nBits - 7) {
+ // force a call to gmallocn(-1,...), which will throw an exception
+ inputLineSize = -1;
+ }
+ inputLine = (char *)gmallocn(inputLineSize, sizeof(char));
+ if (nBits == 8) {
+ imgLine = (Guchar *)inputLine;
} else {
- imgLineSize = nVals;
+ if (nBits == 1) {
+ imgLineSize = (nVals + 7) & ~7;
+ } else {
+ imgLineSize = nVals;
+ }
+ if (width > INT_MAX / nComps) {
+ // force a call to gmallocn(-1,...), which will throw an exception
+ imgLineSize = -1;
+ }
+ imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
}
- imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
imgIdx = nVals;
}
ImageStream::~ImageStream() {
- gfree(imgLine);
+ if (imgLine != (Guchar *)inputLine) {
+ gfree(imgLine);
+ }
+ gfree(inputLine);
}
void ImageStream::reset() {
@@ -339,7 +369,9 @@ GBool ImageStream::getPixel(Guchar *pix) {
int i;
if (imgIdx >= nVals) {
- getLine();
+ if (!getLine()) {
+ return gFalse;
+ }
imgIdx = 0;
}
for (i = 0; i < nComps; ++i) {
@@ -353,10 +385,15 @@ Guchar *ImageStream::getLine() {
int bits;
int c;
int i;
+ char *p;
+ if (str->getBlock(inputLine, inputLineSize) != inputLineSize) {
+ return NULL;
+ }
if (nBits == 1) {
+ p = inputLine;
for (i = 0; i < nVals; i += 8) {
- c = str->getChar();
+ c = *p++;
imgLine[i+0] = (Guchar)((c >> 7) & 1);
imgLine[i+1] = (Guchar)((c >> 6) & 1);
imgLine[i+2] = (Guchar)((c >> 5) & 1);
@@ -367,16 +404,15 @@ Guchar *ImageStream::getLine() {
imgLine[i+7] = (Guchar)(c & 1);
}
} else if (nBits == 8) {
- for (i = 0; i < nVals; ++i) {
- imgLine[i] = str->getChar();
- }
+ // special case: imgLine == inputLine
} else {
bitMask = (1 << nBits) - 1;
buf = 0;
bits = 0;
+ p = inputLine;
for (i = 0; i < nVals; ++i) {
if (bits < nBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
+ buf = (buf << 8) | (*p++ & 0xff);
bits += 8;
}
imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
@@ -387,12 +423,7 @@ Guchar *ImageStream::getLine() {
}
void ImageStream::skipLine() {
- int n, i;
-
- n = (nVals * nBits + 7) >> 3;
- for (i = 0; i < n; ++i) {
- str->getChar();
- }
+ str->getBlock(inputLine, inputLineSize);
}
//------------------------------------------------------------------------
@@ -410,15 +441,13 @@ StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
ok = gFalse;
nVals = width * nComps;
- if (width <= 0 || nComps <= 0 || nBits <= 0 ||
- nComps >= INT_MAX / nBits ||
- width >= INT_MAX / nComps / nBits ||
- nVals * nBits + 7 < 0) {
- return;
- }
pixBytes = (nComps * nBits + 7) >> 3;
rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
- if (rowBytes <= 0) {
+ if (width <= 0 || nComps <= 0 || nBits <= 0 ||
+ nComps > gfxColorMaxComps ||
+ nBits > 16 ||
+ width >= INT_MAX / nComps || // check for overflow in nVals
+ nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
return;
}
predLine = (Guchar *)gmalloc(rowBytes);
@@ -450,6 +479,27 @@ int StreamPredictor::getChar() {
return predLine[predIdx++];
}
+int StreamPredictor::getBlock(char *blk, int size) {
+ int n, m;
+
+ n = 0;
+ while (n < size) {
+ if (predIdx >= rowBytes) {
+ if (!getNextLine()) {
+ break;
+ }
+ }
+ m = rowBytes - predIdx;
+ if (m > size - n) {
+ m = size - n;
+ }
+ memcpy(blk + n, predLine + predIdx, m);
+ predIdx += m;
+ n += m;
+ }
+ return n;
+}
+
GBool StreamPredictor::getNextLine() {
int curPred;
Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
@@ -625,10 +675,31 @@ void FileStream::close() {
}
}
+int FileStream::getBlock(char *blk, int size) {
+ int n, m;
+
+ n = 0;
+ while (n < size) {
+ if (bufPtr >= bufEnd) {
+ if (!fillBuf()) {
+ break;
+ }
+ }
+ m = (int)(bufEnd - bufPtr);
+ if (m > size - n) {
+ m = size - n;
+ }
+ memcpy(blk + n, bufPtr, m);
+ bufPtr += m;
+ n += m;
+ }
+ return n;
+}
+
GBool FileStream::fillBuf() {
int n;
- bufPos += bufEnd - buf;
+ bufPos += (int)(bufEnd - buf);
bufPtr = bufEnd = buf;
if (limited && bufPos >= start + length) {
return gFalse;
@@ -638,7 +709,7 @@ GBool FileStream::fillBuf() {
} else {
n = fileStreamBufSize;
}
- n = fread(buf, 1, n, f);
+ n = (int)fread(buf, 1, n, f);
bufEnd = buf + n;
if (bufPtr >= bufEnd) {
return gFalse;
@@ -671,10 +742,6 @@ void FileStream::setPos(Guint pos, int dir) {
#endif
if (pos > size)
pos = (Guint)size;
-#ifdef __CYGWIN32__
- //~ work around a bug in cygwin's implementation of fseek
- rewind(f);
-#endif
#if HAVE_FSEEKO
fseeko(f, -(int)pos, SEEK_END);
bufPos = (Guint)ftello(f);
@@ -736,6 +803,22 @@ void MemStream::reset() {
void MemStream::close() {
}
+int MemStream::getBlock(char *blk, int size) {
+ int n;
+
+ if (size <= 0) {
+ return 0;
+ }
+ if (bufEnd - bufPtr < size) {
+ n = (int)(bufEnd - bufPtr);
+ } else {
+ n = size;
+ }
+ memcpy(blk, bufPtr, n);
+ bufPtr += n;
+ return n;
+}
+
void MemStream::setPos(Guint pos, int dir) {
Guint i;
@@ -775,7 +858,7 @@ EmbedStream::~EmbedStream() {
Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
Guint lengthA, Object *dictA) {
- error(-1, "Internal: called makeSubStream() on EmbedStream");
+ error(errInternal, -1, "Called makeSubStream() on EmbedStream");
return NULL;
}
@@ -794,17 +877,27 @@ int EmbedStream::lookChar() {
return str->lookChar();
}
+int EmbedStream::getBlock(char *blk, int size) {
+ if (size <= 0) {
+ return 0;
+ }
+ if (limited && length < (Guint)size) {
+ size = (int)length;
+ }
+ return str->getBlock(blk, size);
+}
+
void EmbedStream::setPos(Guint pos, int dir) {
- error(-1, "Internal: called setPos() on EmbedStream");
+ error(errInternal, -1, "Called setPos() on EmbedStream");
}
Guint EmbedStream::getStart() {
- error(-1, "Internal: called getStart() on EmbedStream");
+ error(errInternal, -1, "Called getStart() on EmbedStream");
return 0;
}
void EmbedStream::moveStart(int delta) {
- error(-1, "Internal: called moveStart() on EmbedStream");
+ error(errInternal, -1, "Called moveStart() on EmbedStream");
}
//------------------------------------------------------------------------
@@ -861,7 +954,8 @@ int ASCIIHexStream::lookChar() {
eof = gTrue;
x = 0;
} else {
- error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
+ error(errSyntaxError, getPos(),
+ "Illegal character <{0:02x}> in ASCIIHex stream", c1);
x = 0;
}
if (c2 >= '0' && c2 <= '9') {
@@ -874,13 +968,14 @@ int ASCIIHexStream::lookChar() {
eof = gTrue;
x = 0;
} else {
- error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
+ error(errSyntaxError, getPos(),
+ "Illegal character <{0:02x}> in ASCIIHex stream", c2);
}
buf = x & 0xff;
return buf;
}
-GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
+GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 2) {
@@ -961,7 +1056,7 @@ int ASCII85Stream::lookChar() {
return b[index];
}
-GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
+GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 2) {
@@ -1049,6 +1144,33 @@ int LZWStream::getRawChar() {
return seqBuf[seqIndex++];
}
+int LZWStream::getBlock(char *blk, int size) {
+ int n, m;
+
+ if (pred) {
+ return pred->getBlock(blk, size);
+ }
+ if (eof) {
+ return 0;
+ }
+ n = 0;
+ while (n < size) {
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ break;
+ }
+ }
+ m = seqLength - seqIndex;
+ if (m > size - n) {
+ m = size - n;
+ }
+ memcpy(blk + n, seqBuf + seqIndex, m);
+ seqIndex += m;
+ n += m;
+ }
+ return n;
+}
+
void LZWStream::reset() {
str->reset();
eof = gFalse;
@@ -1078,7 +1200,8 @@ GBool LZWStream::processNextCode() {
goto start;
}
if (nextCode >= 4097) {
- error(getPos(), "Bad LZW stream - expected clear-table code");
+ error(errSyntaxError, getPos(),
+ "Bad LZW stream - expected clear-table code");
clearTable();
}
@@ -1098,7 +1221,7 @@ GBool LZWStream::processNextCode() {
seqBuf[seqLength] = newChar;
++seqLength;
} else {
- error(getPos(), "Bad LZW stream - unexpected code");
+ error(errSyntaxError, getPos(), "Bad LZW stream - unexpected code");
eof = gTrue;
return gFalse;
}
@@ -1147,7 +1270,7 @@ int LZWStream::getCode() {
return code;
}
-GString *LZWStream::getPSFilter(int psLevel, char *indent) {
+GString *LZWStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 2 || pred) {
@@ -1188,7 +1311,28 @@ void RunLengthStream::reset() {
eof = gFalse;
}
-GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
+int RunLengthStream::getBlock(char *blk, int size) {
+ int n, m;
+
+ n = 0;
+ while (n < size) {
+ if (bufPtr >= bufEnd) {
+ if (!fillBuf()) {
+ break;
+ }
+ }
+ m = (int)(bufEnd - bufPtr);
+ if (m > size - n) {
+ m = size - n;
+ }
+ memcpy(blk + n, bufPtr, m);
+ bufPtr += m;
+ n += m;
+ }
+ return n;
+}
+
+GString *RunLengthStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 2) {
@@ -1245,23 +1389,26 @@ CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
columns = columnsA;
if (columns < 1) {
columns = 1;
- }
- if (columns + 4 <= 0) {
- columns = INT_MAX - 4;
+ } else if (columns > INT_MAX - 2) {
+ columns = INT_MAX - 2;
}
rows = rowsA;
endOfBlock = endOfBlockA;
black = blackA;
- refLine = (short *)gmallocn(columns + 3, sizeof(short));
- codingLine = (short *)gmallocn(columns + 2, sizeof(short));
+ // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
+ // ---> max codingLine size = columns + 1
+ // refLine has one extra guard entry at the end
+ // ---> max refLine size = columns + 2
+ codingLine = (int *)gmallocn(columns + 1, sizeof(int));
+ refLine = (int *)gmallocn(columns + 2, sizeof(int));
eof = gFalse;
row = 0;
nextLine2D = encoding < 0;
inputBits = 0;
- codingLine[0] = 0;
- codingLine[1] = refLine[2] = columns;
- a0 = 1;
+ codingLine[0] = columns;
+ a0i = 0;
+ outputBits = 0;
buf = EOF;
}
@@ -1273,16 +1420,16 @@ CCITTFaxStream::~CCITTFaxStream() {
}
void CCITTFaxStream::reset() {
- short code1;
+ int code1;
str->reset();
eof = gFalse;
row = 0;
nextLine2D = encoding < 0;
inputBits = 0;
- codingLine[0] = 0;
- codingLine[1] = columns;
- a0 = 1;
+ codingLine[0] = columns;
+ a0i = 0;
+ outputBits = 0;
buf = EOF;
// skip any initial zero bits and end-of-line marker, and get the 2D
@@ -1292,6 +1439,7 @@ void CCITTFaxStream::reset() {
}
if (code1 == 0x001) {
eatBits(12);
+ endOfLine = gTrue;
}
if (encoding > 0) {
nextLine2D = !lookBits(1);
@@ -1299,234 +1447,278 @@ void CCITTFaxStream::reset() {
}
}
+inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
+ if (a1 > codingLine[a0i]) {
+ if (a1 > columns) {
+ error(errSyntaxError, getPos(),
+ "CCITTFax row is wrong length ({0:d})", a1);
+ err = gTrue;
+ a1 = columns;
+ }
+ if ((a0i & 1) ^ blackPixels) {
+ ++a0i;
+ }
+ codingLine[a0i] = a1;
+ }
+}
+
+inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
+ if (a1 > codingLine[a0i]) {
+ if (a1 > columns) {
+ error(errSyntaxError, getPos(),
+ "CCITTFax row is wrong length ({0:d})", a1);
+ err = gTrue;
+ a1 = columns;
+ }
+ if ((a0i & 1) ^ blackPixels) {
+ ++a0i;
+ }
+ codingLine[a0i] = a1;
+ } else if (a1 < codingLine[a0i]) {
+ if (a1 < 0) {
+ error(errSyntaxError, getPos(), "Invalid CCITTFax code");
+ err = gTrue;
+ a1 = 0;
+ }
+ while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
+ --a0i;
+ }
+ codingLine[a0i] = a1;
+ }
+}
+
int CCITTFaxStream::lookChar() {
- short code1, code2, code3;
- int a0New;
- GBool err, gotEOL;
- int ret;
- int bits, i;
-
- // if at eof just return EOF
- if (eof && codingLine[a0] >= columns) {
- return EOF;
+ int code1, code2, code3;
+ int b1i, blackPixels, i, bits;
+ GBool gotEOL;
+
+ if (buf != EOF) {
+ return buf;
}
// read the next row
- err = gFalse;
- if (codingLine[a0] >= columns) {
+ if (outputBits == 0) {
+
+ // if at eof just return EOF
+ if (eof) {
+ return EOF;
+ }
+
+ err = gFalse;
// 2-D encoding
if (nextLine2D) {
- // 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;
- do {
+ refLine[i++] = columns;
+ refLine[i] = columns;
+ codingLine[0] = 0;
+ a0i = 0;
+ b1i = 0;
+ blackPixels = 0;
+ // invariant:
+ // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
+ // <= columns
+ // exception at left edge:
+ // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
+ // exception at right edge:
+ // refLine[b1i] = refLine[b1i+1] = columns is possible
+ while (codingLine[a0i] < columns) {
code1 = getTwoDimCode();
switch (code1) {
case twoDimPass:
- if (refLine[b1] < columns) {
- a0New = refLine[b1 + 1];
- b1 += 2;
+ addPixels(refLine[b1i + 1], blackPixels);
+ if (refLine[b1i + 1] < columns) {
+ b1i += 2;
}
break;
case twoDimHoriz:
- if ((a0 & 1) == 0) {
- code1 = code2 = 0;
+ code1 = code2 = 0;
+ if (blackPixels) {
do {
- code1 += code3 = getWhiteCode();
+ code1 += code3 = getBlackCode();
} while (code3 >= 64);
do {
- code2 += code3 = getBlackCode();
+ code2 += code3 = getWhiteCode();
} while (code3 >= 64);
} else {
- code1 = code2 = 0;
do {
- code1 += code3 = getBlackCode();
+ code1 += code3 = getWhiteCode();
} while (code3 >= 64);
do {
- code2 += code3 = getWhiteCode();
+ code2 += code3 = getBlackCode();
} while (code3 >= 64);
}
- if (code1 > 0 || code2 > 0) {
- if (a0New + code1 <= columns) {
- codingLine[a0 + 1] = a0New + code1;
- } else {
- codingLine[a0 + 1] = columns;
- }
- ++a0;
- if (codingLine[a0] + code2 <= columns) {
- codingLine[a0 + 1] = codingLine[a0] + code2;
- } else {
- codingLine[a0 + 1] = columns;
- }
- ++a0;
- a0New = codingLine[a0];
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ addPixels(codingLine[a0i] + code1, blackPixels);
+ if (codingLine[a0i] < columns) {
+ addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
+ }
+ break;
+ case twoDimVertR3:
+ addPixels(refLine[b1i] + 3, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
}
break;
- case twoDimVert0:
- if (refLine[b1] < columns) {
- a0New = codingLine[++a0] = refLine[b1];
- ++b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ case twoDimVertR2:
+ addPixels(refLine[b1i] + 2, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
- } else {
- a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertR1:
- if (refLine[b1] + 1 < columns) {
- a0New = codingLine[++a0] = refLine[b1] + 1;
- ++b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ addPixels(refLine[b1i] + 1, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
- } else {
- a0New = codingLine[++a0] = columns;
}
break;
- case twoDimVertL1:
- if (refLine[b1] - 1 > a0New || (a0 == 0 && refLine[b1] == 1)) {
- a0New = codingLine[++a0] = refLine[b1] - 1;
- --b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ case twoDimVert0:
+ addPixels(refLine[b1i], blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ ++b1i;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
}
break;
- case twoDimVertR2:
- if (refLine[b1] + 2 < columns) {
- a0New = codingLine[++a0] = refLine[b1] + 2;
- ++b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ case twoDimVertL3:
+ addPixelsNeg(refLine[b1i] - 3, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
- } else {
- a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertL2:
- if (refLine[b1] - 2 > a0New || (a0 == 0 && refLine[b1] == 2)) {
- a0New = codingLine[++a0] = refLine[b1] - 2;
- --b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ addPixelsNeg(refLine[b1i] - 2, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
}
- }
- break;
- case twoDimVertR3:
- if (refLine[b1] + 3 < columns) {
- a0New = codingLine[++a0] = refLine[b1] + 3;
- ++b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
- } else {
- a0New = codingLine[++a0] = columns;
}
break;
- case twoDimVertL3:
- if (refLine[b1] - 3 > a0New || (a0 == 0 && refLine[b1] == 3)) {
- a0New = codingLine[++a0] = refLine[b1] - 3;
- --b1;
- while (refLine[b1] <= a0New && refLine[b1] < columns) {
- b1 += 2;
+ case twoDimVertL1:
+ addPixelsNeg(refLine[b1i] - 1, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[a0i] < columns) {
+ if (b1i > 0) {
+ --b1i;
+ } else {
+ ++b1i;
+ }
+ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+ b1i += 2;
}
}
break;
case EOF:
+ addPixels(columns, 0);
eof = gTrue;
- codingLine[a0 = 0] = columns;
- return EOF;
+ break;
default:
- error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
+ error(errSyntaxError, getPos(),
+ "Bad 2D code {0:04x} in CCITTFax stream", code1);
+ addPixels(columns, 0);
err = gTrue;
break;
}
- } while (codingLine[a0] < columns);
+ }
// 1-D encoding
} else {
- codingLine[a0 = 0] = 0;
- while (1) {
+ codingLine[0] = 0;
+ a0i = 0;
+ blackPixels = 0;
+ while (codingLine[a0i] < columns) {
code1 = 0;
- do {
- code1 += code3 = getWhiteCode();
- } while (code3 >= 64);
- codingLine[a0+1] = codingLine[a0] + code1;
- ++a0;
- 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) {
- break;
+ if (blackPixels) {
+ do {
+ code1 += code3 = getBlackCode();
+ } while (code3 >= 64);
+ } else {
+ do {
+ code1 += code3 = getWhiteCode();
+ } while (code3 >= 64);
}
+ addPixels(codingLine[a0i] + code1, blackPixels);
+ blackPixels ^= 1;
}
}
- if (codingLine[a0] != columns) {
- error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
- // force the row to be the correct length
- while (codingLine[a0] > columns) {
- --a0;
- }
- codingLine[++a0] = columns;
- err = gTrue;
- }
-
- // byte-align the row
- if (byteAlign) {
- inputBits &= ~7;
- }
-
// check for end-of-line marker, skipping over any extra zero bits
+ // (if EncodedByteAlign is true and EndOfLine is false, there can
+ // be "false" EOL markers -- i.e., if the last n unused bits in
+ // row i are set to zero, and the first 11-n bits in row i+1
+ // happen to be zero -- so we don't look for EOL markers in this
+ // case)
gotEOL = gFalse;
if (!endOfBlock && row == rows - 1) {
eof = gTrue;
- } else {
+ } else if (endOfLine || !byteAlign) {
code1 = lookBits(12);
- while (code1 == 0) {
- eatBits(1);
- code1 = lookBits(12);
+ if (endOfLine) {
+ while (code1 != EOF && code1 != 0x001) {
+ eatBits(1);
+ code1 = lookBits(12);
+ }
+ } else {
+ while (code1 == 0) {
+ eatBits(1);
+ code1 = lookBits(12);
+ }
}
if (code1 == 0x001) {
eatBits(12);
gotEOL = gTrue;
- } else if (code1 == EOF) {
- eof = gTrue;
}
}
+ // byte-align the row
+ // (Adobe apparently doesn't do byte alignment after EOL markers
+ // -- I've seen CCITT image data streams in two different formats,
+ // both with the byteAlign flag set:
+ // 1. xx:x0:01:yy:yy
+ // 2. xx:00:1y:yy:yy
+ // where xx is the previous line, yy is the next line, and colons
+ // separate bytes.)
+ if (byteAlign && !gotEOL) {
+ inputBits &= ~7;
+ }
+
+ // check for end of stream
+ if (lookBits(1) == EOF) {
+ eof = gTrue;
+ }
+
// get 2D encoding tag
if (!eof && encoding > 0) {
nextLine2D = !lookBits(1);
@@ -1534,6 +1726,15 @@ int CCITTFaxStream::lookChar() {
}
// check for end-of-block marker
+ if (endOfBlock && !endOfLine && byteAlign) {
+ // in this case, we didn't check for an EOL code above, so we
+ // need to check here
+ code1 = lookBits(24);
+ if (code1 == 0x001001) {
+ eatBits(12);
+ gotEOL = gTrue;
+ }
+ }
if (endOfBlock && gotEOL) {
code1 = lookBits(12);
if (code1 == 0x001) {
@@ -1546,7 +1747,8 @@ int CCITTFaxStream::lookChar() {
for (i = 0; i < 4; ++i) {
code1 = lookBits(12);
if (code1 != 0x001) {
- error(getPos(), "Bad RTC code in CCITTFax stream");
+ error(errSyntaxError, getPos(),
+ "Bad RTC code in CCITTFax stream");
}
eatBits(12);
if (encoding > 0) {
@@ -1562,14 +1764,17 @@ int CCITTFaxStream::lookChar() {
// this if we know the stream contains end-of-line markers because
// the "just plow on" technique tends to work better otherwise
} else if (err && endOfLine) {
- do {
+ while (1) {
+ code1 = lookBits(13);
if (code1 == EOF) {
eof = gTrue;
return EOF;
}
+ if ((code1 >> 1) == 0x001) {
+ break;
+ }
eatBits(1);
- code1 = lookBits(13);
- } while ((code1 >> 1) != 0x001);
+ }
eatBits(12);
if (encoding > 0) {
eatBits(1);
@@ -1577,11 +1782,11 @@ int CCITTFaxStream::lookChar() {
}
}
- a0 = 0;
- outputBits = codingLine[1] - codingLine[0];
- if (outputBits == 0) {
- a0 = 1;
- outputBits = codingLine[2] - codingLine[1];
+ // set up for output
+ if (codingLine[0] > 0) {
+ outputBits = codingLine[a0i = 0];
+ } else {
+ outputBits = codingLine[a0i = 1];
}
++row;
@@ -1589,58 +1794,65 @@ int CCITTFaxStream::lookChar() {
// get a byte
if (outputBits >= 8) {
- ret = ((a0 & 1) == 0) ? 0xff : 0x00;
- if ((outputBits -= 8) == 0) {
- ++a0;
- if (codingLine[a0] < columns) {
- outputBits = codingLine[a0 + 1] - codingLine[a0];
- }
+ buf = (a0i & 1) ? 0x00 : 0xff;
+ outputBits -= 8;
+ if (outputBits == 0 && codingLine[a0i] < columns) {
+ ++a0i;
+ outputBits = codingLine[a0i] - codingLine[a0i - 1];
}
} else {
bits = 8;
- ret = 0;
+ buf = 0;
do {
if (outputBits > bits) {
- i = bits;
- bits = 0;
- if ((a0 & 1) == 0) {
- ret |= 0xff >> (8 - i);
+ buf <<= bits;
+ if (!(a0i & 1)) {
+ buf |= 0xff >> (8 - bits);
}
- outputBits -= i;
+ outputBits -= bits;
+ bits = 0;
} else {
- i = outputBits;
- bits -= outputBits;
- if ((a0 & 1) == 0) {
- ret |= (0xff >> (8 - i)) << bits;
+ buf <<= outputBits;
+ if (!(a0i & 1)) {
+ buf |= 0xff >> (8 - outputBits);
}
+ bits -= outputBits;
outputBits = 0;
- ++a0;
- if (codingLine[a0] < columns) {
- outputBits = codingLine[a0 + 1] - codingLine[a0];
+ if (codingLine[a0i] < columns) {
+ ++a0i;
+ outputBits = codingLine[a0i] - codingLine[a0i - 1];
+ } else if (bits > 0) {
+ buf <<= bits;
+ bits = 0;
}
}
- } while (bits > 0 && codingLine[a0] < columns);
+ } while (bits);
+ }
+ if (black) {
+ buf ^= 0xff;
}
- buf = black ? (ret ^ 0xff) : ret;
return buf;
}
short CCITTFaxStream::getTwoDimCode() {
- short code;
+ int code;
CCITTCode *p;
int n;
code = 0; // make gcc happy
if (endOfBlock) {
- code = lookBits(7);
- p = &twoDimTab1[code];
- if (p->bits > 0) {
- eatBits(p->bits);
- return p->n;
+ if ((code = lookBits(7)) != EOF) {
+ p = &twoDimTab1[code];
+ if (p->bits > 0) {
+ eatBits(p->bits);
+ return p->n;
+ }
}
} else {
for (n = 1; n <= 7; ++n) {
- code = lookBits(n);
+ if ((code = lookBits(n)) == EOF) {
+ break;
+ }
if (n < 7) {
code <<= 7 - n;
}
@@ -1651,7 +1863,8 @@ short CCITTFaxStream::getTwoDimCode() {
}
}
}
- error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
+ error(errSyntaxError, getPos(),
+ "Bad two dim code ({0:04x}) in CCITTFax stream", code);
return EOF;
}
@@ -1663,6 +1876,9 @@ short CCITTFaxStream::getWhiteCode() {
code = 0; // make gcc happy
if (endOfBlock) {
code = lookBits(12);
+ if (code == EOF) {
+ return 1;
+ }
if ((code >> 5) == 0) {
p = &whiteTab1[code];
} else {
@@ -1675,6 +1891,9 @@ short CCITTFaxStream::getWhiteCode() {
} else {
for (n = 1; n <= 9; ++n) {
code = lookBits(n);
+ if (code == EOF) {
+ return 1;
+ }
if (n < 9) {
code <<= 9 - n;
}
@@ -1686,6 +1905,9 @@ short CCITTFaxStream::getWhiteCode() {
}
for (n = 11; n <= 12; ++n) {
code = lookBits(n);
+ if (code == EOF) {
+ return 1;
+ }
if (n < 12) {
code <<= 12 - n;
}
@@ -1696,7 +1918,8 @@ short CCITTFaxStream::getWhiteCode() {
}
}
}
- error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
+ error(errSyntaxError, getPos(),
+ "Bad white code ({0:04x}) in CCITTFax stream", code);
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
eatBits(1);
@@ -1711,9 +1934,12 @@ short CCITTFaxStream::getBlackCode() {
code = 0; // make gcc happy
if (endOfBlock) {
code = lookBits(13);
+ if (code == EOF) {
+ return 1;
+ }
if ((code >> 7) == 0) {
p = &blackTab1[code];
- } else if ((code >> 9) == 0) {
+ } else if ((code >> 9) == 0 && (code >> 7) != 0) {
p = &blackTab2[(code >> 1) - 64];
} else {
p = &blackTab3[code >> 7];
@@ -1725,6 +1951,9 @@ short CCITTFaxStream::getBlackCode() {
} else {
for (n = 2; n <= 6; ++n) {
code = lookBits(n);
+ if (code == EOF) {
+ return 1;
+ }
if (n < 6) {
code <<= 6 - n;
}
@@ -1736,6 +1965,9 @@ short CCITTFaxStream::getBlackCode() {
}
for (n = 7; n <= 12; ++n) {
code = lookBits(n);
+ if (code == EOF) {
+ return 1;
+ }
if (n < 12) {
code <<= 12 - n;
}
@@ -1749,6 +1981,9 @@ short CCITTFaxStream::getBlackCode() {
}
for (n = 10; n <= 13; ++n) {
code = lookBits(n);
+ if (code == EOF) {
+ return 1;
+ }
if (n < 13) {
code <<= 13 - n;
}
@@ -1759,7 +1994,8 @@ short CCITTFaxStream::getBlackCode() {
}
}
}
- error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
+ error(errSyntaxError, getPos(),
+ "Bad black code ({0:04x}) in CCITTFax stream", code);
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
eatBits(1);
@@ -1778,15 +2014,15 @@ short CCITTFaxStream::lookBits(int n) {
// than are available, but there may still be a valid code in
// however many bits are available -- we need to return correct
// data in this case
- return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
+ return (inputBuf << (n - inputBits)) & (0xffffffff >> (32 - n));
}
inputBuf = (inputBuf << 8) + c;
inputBits += 8;
}
- return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
+ return (inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n));
}
-GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
+GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
char s1[50];
@@ -1963,6 +2199,12 @@ void DCTStream::reset() {
// allocate a buffer for the whole image
bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
+ if (bufWidth <= 0 || bufHeight <= 0 ||
+ bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
+ error(errSyntaxError, getPos(), "Invalid image size in DCT stream");
+ y = height;
+ return;
+ }
for (i = 0; i < numComps; ++i) {
frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
@@ -2106,7 +2348,8 @@ GBool DCTStream::readMCURow() {
if (restartInterval > 0 && restartCtr == 0) {
c = readMarker();
if (c != restartMarker) {
- error(getPos(), "Bad DCT data: incorrect restart marker");
+ error(errSyntaxError, getPos(),
+ "Bad DCT data: incorrect restart marker");
return gFalse;
}
if (++restartMarker == 0xd8)
@@ -2239,7 +2482,8 @@ void DCTStream::readScan() {
if (restartInterval > 0 && restartCtr == 0) {
c = readMarker();
if (c != restartMarker) {
- error(getPos(), "Bad DCT data: incorrect restart marker");
+ error(errSyntaxError, getPos(),
+ "Bad DCT data: incorrect restart marker");
return;
}
if (++restartMarker == 0xd8) {
@@ -2425,7 +2669,7 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
// ZRL
if (c == 0xf0) {
k = 0;
- while (k < 16) {
+ while (k < 16 && i <= scanInfo.lastCoeff) {
j = dctZigZag[i++];
if (data[j] == 0) {
++k;
@@ -2471,10 +2715,10 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
if ((amp = readAmp(size)) == 9999) {
return gFalse;
}
- k = 0;
- do {
+ j = 0; // make gcc happy
+ for (k = 0; k <= run && i <= scanInfo.lastCoeff; ++k) {
j = dctZigZag[i++];
- while (data[j] != 0) {
+ while (data[j] != 0 && i <= scanInfo.lastCoeff) {
if ((bit = readBit()) == EOF) {
return gFalse;
}
@@ -2483,8 +2727,7 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
}
j = dctZigZag[i++];
}
- ++k;
- } while (k <= run);
+ }
data[j] = amp << scanInfo.al;
}
}
@@ -2797,19 +3040,23 @@ int DCTStream::readHuffSym(DCTHuffTable *table) {
codeBits = 0;
do {
// add a bit to the code
- if ((bit = readBit()) == EOF)
+ if ((bit = readBit()) == EOF) {
return 9999;
+ }
code = (code << 1) + bit;
++codeBits;
// look up code
+ if (code < table->firstCode[codeBits]) {
+ break;
+ }
if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
code -= table->firstCode[codeBits];
return table->sym[table->firstSym[codeBits] + code];
}
} while (codeBits < 16);
- error(getPos(), "Bad Huffman code in DCT stream");
+ error(errSyntaxError, getPos(), "Bad Huffman code in DCT stream");
return 9999;
}
@@ -2840,7 +3087,7 @@ int DCTStream::readBit() {
c2 = str->getChar();
} while (c2 == 0xff);
if (c2 != 0x00) {
- error(getPos(), "Bad DCT data: missing 00 after ff");
+ error(errSyntaxError, getPos(), "Bad DCT data: missing 00 after ff");
return EOF;
}
}
@@ -2910,7 +3157,7 @@ GBool DCTStream::readHeader() {
}
break;
case EOF:
- error(getPos(), "Bad DCT header");
+ error(errSyntaxError, getPos(), "Bad DCT header");
return gFalse;
default:
// skip APPn / COM / etc.
@@ -2920,7 +3167,7 @@ GBool DCTStream::readHeader() {
str->getChar();
}
} else {
- error(getPos(), "Unknown DCT marker <%02x>", c);
+ error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c);
return gFalse;
}
break;
@@ -2942,12 +3189,12 @@ GBool DCTStream::readBaselineSOF() {
width = read16();
numComps = str->getChar();
if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream");
+ error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
numComps = 0;
return gFalse;
}
if (prec != 8) {
- error(getPos(), "Bad DCT precision %d", prec);
+ error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
return gFalse;
}
for (i = 0; i < numComps; ++i) {
@@ -2956,6 +3203,15 @@ GBool DCTStream::readBaselineSOF() {
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
+ if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
+ compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
+ error(errSyntaxError, getPos(), "Bad DCT sampling factor");
+ return gFalse;
+ }
+ if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
+ error(errSyntaxError, getPos(), "Bad DCT quant table selector");
+ return gFalse;
+ }
}
progressive = gFalse;
return gTrue;
@@ -2973,12 +3229,12 @@ GBool DCTStream::readProgressiveSOF() {
width = read16();
numComps = str->getChar();
if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream");
+ error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
numComps = 0;
return gFalse;
}
if (prec != 8) {
- error(getPos(), "Bad DCT precision %d", prec);
+ error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
return gFalse;
}
for (i = 0; i < numComps; ++i) {
@@ -2987,6 +3243,15 @@ GBool DCTStream::readProgressiveSOF() {
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
+ if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
+ compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
+ error(errSyntaxError, getPos(), "Bad DCT sampling factor");
+ return gFalse;
+ }
+ if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
+ error(errSyntaxError, getPos(), "Bad DCT quant table selector");
+ return gFalse;
+ }
}
progressive = gTrue;
return gTrue;
@@ -3000,13 +3265,13 @@ GBool DCTStream::readScanInfo() {
length = read16() - 2;
scanInfo.numComps = str->getChar();
if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream");
+ error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
scanInfo.numComps = 0;
return gFalse;
}
--length;
if (length != 2 * scanInfo.numComps + 3) {
- error(getPos(), "Bad DCT scan info block");
+ error(errSyntaxError, getPos(), "Bad DCT scan info block");
return gFalse;
}
interleaved = scanInfo.numComps == numComps;
@@ -3027,7 +3292,8 @@ GBool DCTStream::readScanInfo() {
}
}
if (j == numComps) {
- error(getPos(), "Bad DCT component ID in scan info block");
+ error(errSyntaxError, getPos(),
+ "Bad DCT component ID in scan info block");
return gFalse;
}
}
@@ -3038,6 +3304,12 @@ GBool DCTStream::readScanInfo() {
}
scanInfo.firstCoeff = str->getChar();
scanInfo.lastCoeff = str->getChar();
+ if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
+ scanInfo.firstCoeff > scanInfo.lastCoeff) {
+ error(errSyntaxError, getPos(),
+ "Bad DCT coefficient numbers in scan info block");
+ return gFalse;
+ }
c = str->getChar();
scanInfo.ah = (c >> 4) & 0x0f;
scanInfo.al = c & 0x0f;
@@ -3053,7 +3325,7 @@ GBool DCTStream::readQuantTables() {
prec = (index >> 4) & 0x0f;
index &= 0x0f;
if (prec > 1 || index >= 4) {
- error(getPos(), "Bad DCT quantization table");
+ error(errSyntaxError, getPos(), "Bad DCT quantization table");
return gFalse;
}
if (index == numQuantTables) {
@@ -3089,7 +3361,7 @@ GBool DCTStream::readHuffmanTables() {
index = str->getChar();
--length;
if ((index & 0x0f) >= 4) {
- error(getPos(), "Bad DCT Huffman table");
+ error(errSyntaxError, getPos(), "Bad DCT Huffman table");
return gFalse;
}
if (index & 0x10) {
@@ -3126,7 +3398,7 @@ GBool DCTStream::readRestartInterval() {
length = read16();
if (length != 4) {
- error(getPos(), "Bad DCT restart interval");
+ error(errSyntaxError, getPos(), "Bad DCT restart interval");
return gFalse;
}
restartInterval = read16();
@@ -3143,7 +3415,7 @@ GBool DCTStream::readJFIFMarker() {
if (length >= 5) {
for (i = 0; i < 5; ++i) {
if ((c = str->getChar()) == EOF) {
- error(getPos(), "Bad DCT APP0 marker");
+ error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
return gFalse;
}
buf[i] = c;
@@ -3155,7 +3427,7 @@ GBool DCTStream::readJFIFMarker() {
}
while (length > 0) {
if (str->getChar() == EOF) {
- error(getPos(), "Bad DCT APP0 marker");
+ error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
return gFalse;
}
--length;
@@ -3191,7 +3463,7 @@ GBool DCTStream::readAdobeMarker() {
return gTrue;
err:
- error(getPos(), "Bad DCT Adobe APP14 marker");
+ error(errSyntaxError, getPos(), "Bad DCT Adobe APP14 marker");
return gFalse;
}
@@ -3200,7 +3472,7 @@ GBool DCTStream::readTrailer() {
c = readMarker();
if (c != 0xd9) { // EOI
- error(getPos(), "Bad DCT trailer");
+ error(errSyntaxError, getPos(), "Bad DCT trailer");
return gFalse;
}
return gTrue;
@@ -3230,7 +3502,7 @@ int DCTStream::read16() {
return (c1 << 8) + c2;
}
-GString *DCTStream::getPSFilter(int psLevel, char *indent) {
+GString *DCTStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 2) {
@@ -3931,15 +4203,16 @@ void FlateStream::reset() {
if (cmf == EOF || flg == EOF)
return;
if ((cmf & 0x0f) != 0x08) {
- error(getPos(), "Unknown compression method in flate stream");
+ error(errSyntaxError, getPos(),
+ "Unknown compression method in flate stream");
return;
}
if ((((cmf << 8) + flg) % 31) != 0) {
- error(getPos(), "Bad FCHECK in flate stream");
+ error(errSyntaxError, getPos(), "Bad FCHECK in flate stream");
return;
}
if (flg & 0x20) {
- error(getPos(), "FDICT bit set in flate stream");
+ error(errSyntaxError, getPos(), "FDICT bit set in flate stream");
return;
}
@@ -3992,7 +4265,31 @@ int FlateStream::getRawChar() {
return c;
}
-GString *FlateStream::getPSFilter(int psLevel, char *indent) {
+int FlateStream::getBlock(char *blk, int size) {
+ int n;
+
+ if (pred) {
+ return pred->getBlock(blk, size);
+ }
+
+ n = 0;
+ while (n < size) {
+ if (endOfBlock && eof) {
+ break;
+ }
+ if (remain == 0) {
+ readSome();
+ }
+ while (remain && n < size) {
+ blk[n++] = buf[index];
+ index = (index + 1) & flateMask;
+ --remain;
+ }
+ }
+ return n;
+}
+
+GString *FlateStream::getPSFilter(int psLevel, const char *indent) {
GString *s;
if (psLevel < 3 || pred) {
@@ -4069,7 +4366,7 @@ void FlateStream::readSome() {
return;
err:
- error(getPos(), "Unexpected end of file in flate stream");
+ error(errSyntaxError, getPos(), "Unexpected end of file in flate stream");
endOfBlock = eof = gTrue;
remain = 0;
}
@@ -4111,7 +4408,8 @@ GBool FlateStream::startBlock() {
goto err;
check |= (c & 0xff) << 8;
if (check != (~blockLen & 0xffff))
- error(getPos(), "Bad uncompressed block length in flate stream");
+ error(errSyntaxError, getPos(),
+ "Bad uncompressed block length in flate stream");
codeBuf = 0;
codeSize = 0;
@@ -4136,7 +4434,7 @@ GBool FlateStream::startBlock() {
return gTrue;
err:
- error(getPos(), "Bad block header in flate stream");
+ error(errSyntaxError, getPos(), "Bad block header in flate stream");
endOfBlock = eof = gTrue;
return gFalse;
}
@@ -4243,7 +4541,7 @@ GBool FlateStream::readDynamicCodes() {
return gTrue;
err:
- error(getPos(), "Bad dynamic code table in flate stream");
+ error(errSyntaxError, getPos(), "Bad dynamic code table in flate stream");
gfree(codeLenCodeTab.codes);
return gFalse;
}
@@ -4346,6 +4644,52 @@ EOFStream::~EOFStream() {
}
//------------------------------------------------------------------------
+// BufStream
+//------------------------------------------------------------------------
+
+BufStream::BufStream(Stream *strA, int bufSizeA): FilterStream(strA) {
+ bufSize = bufSizeA;
+ buf = (int *)gmallocn(bufSize, sizeof(int));
+}
+
+BufStream::~BufStream() {
+ gfree(buf);
+ delete str;
+}
+
+void BufStream::reset() {
+ int i;
+
+ str->reset();
+ for (i = 0; i < bufSize; ++i) {
+ buf[i] = str->getChar();
+ }
+}
+
+int BufStream::getChar() {
+ int c, i;
+
+ c = buf[0];
+ for (i = 1; i < bufSize; ++i) {
+ buf[i-1] = buf[i];
+ }
+ buf[bufSize - 1] = str->getChar();
+ return c;
+}
+
+int BufStream::lookChar() {
+ return buf[0];
+}
+
+int BufStream::lookChar(int idx) {
+ return buf[idx];
+}
+
+GBool BufStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+//------------------------------------------------------------------------
// FixedLengthEncoder
//------------------------------------------------------------------------
@@ -4407,7 +4751,7 @@ void ASCIIHexEncoder::reset() {
}
GBool ASCIIHexEncoder::fillBuf() {
- static char *hex = "0123456789abcdef";
+ static const char *hex = "0123456789abcdef";
int c;
if (eof) {
@@ -4453,7 +4797,7 @@ void ASCII85Encoder::reset() {
}
GBool ASCII85Encoder::fillBuf() {
- Gulong t;
+ Guint t;
char buf1[5];
int c0, c1, c2, c3;
int n, i;
diff --git a/xpdf/Stream.h b/xpdf/Stream.h
index 85a8469..50710a6 100644
--- a/xpdf/Stream.h
+++ b/xpdf/Stream.h
@@ -50,7 +50,8 @@ enum StreamColorSpaceMode {
// include file dependency loops.
enum CryptAlgorithm {
cryptRC4,
- cryptAES
+ cryptAES,
+ cryptAES256
};
//------------------------------------------------------------------------
@@ -89,6 +90,10 @@ public:
// This is only used by StreamPredictor.
virtual int getRawChar();
+ // Get exactly <size> bytes from stream. Returns the number of
+ // bytes read -- the returned count will be less than <size> at EOF.
+ virtual int getBlock(char *blk, int size);
+
// Get next line from stream.
virtual char *getLine(char *buf, int size);
@@ -101,7 +106,7 @@ public:
virtual void setPos(Guint pos, int dir = 0) = 0;
// Get PostScript command for the filter(s).
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
// Does this stream type potentially contain non-printable chars?
virtual GBool isBinary(GBool last = gTrue) = 0;
@@ -225,6 +230,8 @@ private:
int nComps; // components per pixel
int nBits; // bits per component
int nVals; // components per line
+ int inputLineSize; // input line buffer size
+ char *inputLine; // input line buffer
Guchar *imgLine; // line buffer
int imgIdx; // current index in imgLine
};
@@ -247,6 +254,7 @@ public:
int lookChar();
int getChar();
+ int getBlock(char *blk, int size);
private:
@@ -286,7 +294,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual int getPos() { return bufPos + (bufPtr - buf); }
+ virtual int getBlock(char *blk, int size);
+ virtual int getPos() { return bufPos + (int)(bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
@@ -325,6 +334,7 @@ public:
{ return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
virtual int lookChar()
{ return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
+ virtual int getBlock(char *blk, int size);
virtual int getPos() { return (int)(bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart() { return start; }
@@ -361,6 +371,7 @@ public:
virtual void reset() {}
virtual int getChar();
virtual int lookChar();
+ virtual int getBlock(char *blk, int size);
virtual int getPos() { return str->getPos(); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart();
@@ -387,7 +398,7 @@ public:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -410,7 +421,7 @@ public:
virtual int getChar()
{ int ch = lookChar(); ++index; return ch; }
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -436,7 +447,8 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual int getBlock(char *blk, int size);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -480,7 +492,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual int getBlock(char *blk, int size);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -511,7 +524,7 @@ public:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -526,15 +539,17 @@ private:
GBool eof; // true if at eof
GBool nextLine2D; // true if next line uses 2D encoding
int row; // current row
- int inputBuf; // input buffer
+ Guint inputBuf; // input buffer
int inputBits; // number of bits in input buffer
- short *refLine; // reference line changing elements
- int b1; // index into refLine
- short *codingLine; // coding line changing elements
- int a0; // index into codingLine
+ int *codingLine; // coding line changing elements
+ int *refLine; // reference line changing elements
+ int a0i; // index into codingLine
+ GBool err; // error on current line
int outputBits; // remaining ouput bits
int buf; // character buffer
+ void addPixels(int a1, int blackPixels);
+ void addPixelsNeg(int a1, int blackPixels);
short getTwoDimCode();
short getWhiteCode();
short getBlackCode();
@@ -582,7 +597,7 @@ public:
virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
Stream *getRawStream() { return str; }
@@ -685,7 +700,8 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual int getBlock(char *blk, int size);
+ virtual GString *getPSFilter(int psLevel, const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -738,11 +754,38 @@ public:
virtual void reset() {}
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual int getBlock(char *blk, int size) { return 0; }
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
};
//------------------------------------------------------------------------
+// BufStream
+//------------------------------------------------------------------------
+
+class BufStream: public FilterStream {
+public:
+
+ BufStream(Stream *strA, int bufSizeA);
+ virtual ~BufStream();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue);
+
+ int lookChar(int idx);
+
+private:
+
+ int *buf;
+ int bufSize;
+};
+
+//------------------------------------------------------------------------
// FixedLengthEncoder
//------------------------------------------------------------------------
@@ -755,7 +798,8 @@ public:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue);
virtual GBool isEncoder() { return gTrue; }
@@ -780,7 +824,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -810,7 +855,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -840,7 +886,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
diff --git a/xpdf/TextOutputDev.cc b/xpdf/TextOutputDev.cc
index a78f0ee..971a3fe 100644
--- a/xpdf/TextOutputDev.cc
+++ b/xpdf/TextOutputDev.cc
@@ -172,9 +172,8 @@ public:
TextFontInfo::TextFontInfo(GfxState *state) {
gfxFont = state->getFont();
#if TEXTOUT_WORD_LIST
- fontName = (gfxFont && gfxFont->getOrigName())
- ? gfxFont->getOrigName()->copy()
- : (GString *)NULL;
+ fontName = (gfxFont && gfxFont->getName()) ? gfxFont->getName()->copy()
+ : (GString *)NULL;
flags = gfxFont ? gfxFont->getFlags() : 0;
#endif
}
@@ -196,73 +195,102 @@ GBool TextFontInfo::matches(GfxState *state) {
//------------------------------------------------------------------------
TextWord::TextWord(GfxState *state, int rotA, double x0, double y0,
- int charPosA, TextFontInfo *fontA, double fontSizeA) {
+ TextFontInfo *fontA, double fontSizeA) {
GfxFont *gfxFont;
double x, y, ascent, descent;
+ int wMode;
rot = rotA;
- charPos = charPosA;
- charLen = 0;
font = fontA;
fontSize = fontSizeA;
state->transform(x0, y0, &x, &y);
if ((gfxFont = font->gfxFont)) {
ascent = gfxFont->getAscent() * fontSize;
descent = gfxFont->getDescent() * fontSize;
+ wMode = gfxFont->getWMode();
} else {
// this means that the PDF file draws text without a current font,
// which should never happen
ascent = 0.95 * fontSize;
descent = -0.35 * fontSize;
+ wMode = 0;
}
- switch (rot) {
- case 0:
- yMin = y - ascent;
- yMax = y - descent;
- if (yMin == yMax) {
- // this is a sanity check for a case that shouldn't happen -- but
- // if it does happen, we want to avoid dividing by zero later
- yMin = y;
- yMax = y + 1;
- }
- base = y;
- break;
- case 1:
- xMin = x + descent;
- xMax = x + ascent;
- if (xMin == xMax) {
- // this is a sanity check for a case that shouldn't happen -- but
- // if it does happen, we want to avoid dividing by zero later
+ if (wMode) { // vertical writing mode
+ // NB: the rotation value has been incremented by 1 (in
+ // TextPage::beginWord()) for vertical writing mode
+ switch (rot) {
+ case 0:
+ yMin = y - fontSize;
+ yMax = y;
+ base = y;
+ break;
+ case 1:
xMin = x;
- xMax = x + 1;
- }
- base = x;
- break;
- case 2:
- yMin = y + descent;
- yMax = y + ascent;
- if (yMin == yMax) {
- // this is a sanity check for a case that shouldn't happen -- but
- // if it does happen, we want to avoid dividing by zero later
+ xMax = x + fontSize;
+ base = x;
+ break;
+ case 2:
yMin = y;
- yMax = y + 1;
+ yMax = y + fontSize;
+ base = y;
+ break;
+ case 3:
+ xMin = x - fontSize;
+ xMax = x;
+ base = x;
+ break;
}
- base = y;
- break;
- case 3:
- xMin = x - ascent;
- xMax = x - descent;
- if (xMin == xMax) {
- // this is a sanity check for a case that shouldn't happen -- but
- // if it does happen, we want to avoid dividing by zero later
- xMin = x;
- xMax = x + 1;
+ } else { // horizontal writing mode
+ switch (rot) {
+ case 0:
+ yMin = y - ascent;
+ yMax = y - descent;
+ if (yMin == yMax) {
+ // this is a sanity check for a case that shouldn't happen -- but
+ // if it does happen, we want to avoid dividing by zero later
+ yMin = y;
+ yMax = y + 1;
+ }
+ base = y;
+ break;
+ case 1:
+ xMin = x + descent;
+ xMax = x + ascent;
+ if (xMin == xMax) {
+ // this is a sanity check for a case that shouldn't happen -- but
+ // if it does happen, we want to avoid dividing by zero later
+ xMin = x;
+ xMax = x + 1;
+ }
+ base = x;
+ break;
+ case 2:
+ yMin = y + descent;
+ yMax = y + ascent;
+ if (yMin == yMax) {
+ // this is a sanity check for a case that shouldn't happen -- but
+ // if it does happen, we want to avoid dividing by zero later
+ yMin = y;
+ yMax = y + 1;
+ }
+ base = y;
+ break;
+ case 3:
+ xMin = x - ascent;
+ xMax = x - descent;
+ if (xMin == xMax) {
+ // this is a sanity check for a case that shouldn't happen -- but
+ // if it does happen, we want to avoid dividing by zero later
+ xMin = x;
+ xMax = x + 1;
+ }
+ base = x;
+ break;
}
- base = x;
- break;
}
text = NULL;
edge = NULL;
+ charPos = NULL;
len = size = 0;
spaceAfter = gFalse;
next = NULL;
@@ -287,45 +315,88 @@ TextWord::TextWord(GfxState *state, int rotA, double x0, double y0,
TextWord::~TextWord() {
gfree(text);
gfree(edge);
+ gfree(charPos);
}
void TextWord::addChar(GfxState *state, double x, double y,
- double dx, double dy, Unicode u) {
+ double dx, double dy, int charPosA, int charLen,
+ Unicode u) {
+ int wMode;
+
if (len == size) {
size += 16;
text = (Unicode *)greallocn(text, size, sizeof(Unicode));
edge = (double *)greallocn(edge, size + 1, sizeof(double));
+ charPos = (int *)greallocn(charPos, size + 1, sizeof(int));
}
text[len] = u;
- switch (rot) {
- case 0:
- if (len == 0) {
- xMin = x;
- }
- edge[len] = x;
- xMax = edge[len+1] = x + dx;
- break;
- case 1:
- if (len == 0) {
- yMin = y;
- }
- edge[len] = y;
- yMax = edge[len+1] = y + dy;
- break;
- case 2:
- if (len == 0) {
- xMax = x;
+ charPos[len] = charPosA;
+ charPos[len + 1] = charPosA + charLen;
+ wMode = font->gfxFont ? font->gfxFont->getWMode() : 0;
+ if (wMode) { // vertical writing mode
+ // NB: the rotation value has been incremented by 1 (in
+ // TextPage::beginWord()) for vertical writing mode
+ switch (rot) {
+ case 0:
+ if (len == 0) {
+ xMin = x - fontSize;
+ }
+ edge[len] = x - fontSize;
+ xMax = edge[len+1] = x;
+ break;
+ case 1:
+ if (len == 0) {
+ yMin = y - fontSize;
+ }
+ edge[len] = y - fontSize;
+ yMax = edge[len+1] = y;
+ break;
+ case 2:
+ if (len == 0) {
+ xMax = x + fontSize;
+ }
+ edge[len] = x + fontSize;
+ xMin = edge[len+1] = x;
+ break;
+ case 3:
+ if (len == 0) {
+ yMax = y + fontSize;
+ }
+ edge[len] = y + fontSize;
+ yMin = edge[len+1] = y;
+ break;
}
- edge[len] = x;
- xMin = edge[len+1] = x + dx;
- break;
- case 3:
- if (len == 0) {
- yMax = y;
+ } else { // horizontal writing mode
+ switch (rot) {
+ case 0:
+ if (len == 0) {
+ xMin = x;
+ }
+ edge[len] = x;
+ xMax = edge[len+1] = x + dx;
+ break;
+ case 1:
+ if (len == 0) {
+ yMin = y;
+ }
+ edge[len] = y;
+ yMax = edge[len+1] = y + dy;
+ break;
+ case 2:
+ if (len == 0) {
+ xMax = x;
+ }
+ edge[len] = x;
+ xMin = edge[len+1] = x + dx;
+ break;
+ case 3:
+ if (len == 0) {
+ yMax = y;
+ }
+ edge[len] = y;
+ yMin = edge[len+1] = y + dy;
+ break;
}
- edge[len] = y;
- yMin = edge[len+1] = y + dy;
- break;
}
++len;
}
@@ -349,14 +420,16 @@ void TextWord::merge(TextWord *word) {
size = len + word->len;
text = (Unicode *)greallocn(text, size, sizeof(Unicode));
edge = (double *)greallocn(edge, size + 1, sizeof(double));
+ charPos = (int *)greallocn(charPos, size + 1, sizeof(int));
}
for (i = 0; i < word->len; ++i) {
text[len + i] = word->text[i];
edge[len + i] = word->edge[i];
+ charPos[len + i] = word->charPos[i];
}
edge[len + word->len] = word->edge[word->len];
+ charPos[len + word->len] = word->charPos[word->len];
len += word->len;
- charLen += word->charLen;
}
inline int TextWord::primaryCmp(TextWord *word) {
@@ -545,7 +618,7 @@ void TextPool::addWord(TextWord *word) {
// insert the new word
if (cursor && wordBaseIdx == cursorBaseIdx &&
- word->primaryCmp(cursor) > 0) {
+ word->primaryCmp(cursor) >= 0) {
w0 = cursor;
w1 = cursor->next;
} else {
@@ -741,7 +814,7 @@ void TextLine::coalesce(UnicodeMap *uMap) {
word0->underlined == word1->underlined &&
fabs(word0->fontSize - word1->fontSize) <
maxWordFontSizeDelta * words->fontSize &&
- word1->charPos == word0->charPos + word0->charLen) {
+ word1->charPos[0] == word0->charPos[word0->len]) {
word0->merge(word1);
word0->next = word1->next;
delete word1;
@@ -928,7 +1001,7 @@ void TextLineFrag::computeCoords(GBool oneRot) {
xMax = blk->xMin + d1 * (blk->xMax - blk->xMin);
yMin = blk->yMin + d2 * (blk->yMax - blk->yMin);
yMax = blk->yMin + d3 * (blk->yMax - blk->yMin);
- base = blk->yMin + base * (blk->yMax - blk->yMin);
+ base = blk->yMin + d4 * (blk->yMax - blk->yMin);
break;
case 1:
xMin = blk->xMax - d3 * (blk->xMax - blk->xMin);
@@ -1150,15 +1223,15 @@ void TextBlock::addWord(TextWord *word) {
}
}
-void TextBlock::coalesce(UnicodeMap *uMap) {
+void TextBlock::coalesce(UnicodeMap *uMap, double fixedPitch) {
TextWord *word0, *word1, *word2, *bestWord0, *bestWord1, *lastWord;
TextLine *line, *line0, *line1;
int poolMinBaseIdx, startBaseIdx, minBaseIdx, maxBaseIdx;
int baseIdx, bestWordBaseIdx, idx0, idx1;
double minBase, maxBase;
- double fontSize, delta, priDelta, secDelta;
+ double fontSize, wordSpacing, delta, priDelta, secDelta;
TextLine **lineArray;
- GBool found;
+ GBool found, overlap;
int col1, col2;
int i, j, k;
@@ -1168,11 +1241,7 @@ void TextBlock::coalesce(UnicodeMap *uMap) {
while (word0) {
priDelta = dupMaxPriDelta * word0->fontSize;
secDelta = dupMaxSecDelta * word0->fontSize;
- if (rot == 0 || rot == 3) {
- maxBaseIdx = pool->getBaseIdx(word0->base + secDelta);
- } else {
- maxBaseIdx = pool->getBaseIdx(word0->base - secDelta);
- }
+ maxBaseIdx = pool->getBaseIdx(word0->base + secDelta);
found = gFalse;
word1 = word2 = NULL; // make gcc happy
for (idx1 = idx0; idx1 <= maxBaseIdx; ++idx1) {
@@ -1269,6 +1338,7 @@ void TextBlock::coalesce(UnicodeMap *uMap) {
maxBase = word0->base + maxIntraLineDelta * fontSize;
minBaseIdx = pool->getBaseIdx(minBase);
maxBaseIdx = pool->getBaseIdx(maxBase);
+ wordSpacing = fixedPitch ? fixedPitch : maxWordSpacing * fontSize;
// find the rest of the words in this line
while (1) {
@@ -1277,25 +1347,32 @@ void TextBlock::coalesce(UnicodeMap *uMap) {
// this line
bestWordBaseIdx = 0;
bestWord0 = bestWord1 = NULL;
- for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) {
+ overlap = gFalse;
+ for (baseIdx = minBaseIdx;
+ !overlap && baseIdx <= maxBaseIdx;
+ ++baseIdx) {
for (word0 = NULL, word1 = pool->getPool(baseIdx);
word1;
word0 = word1, word1 = word1->next) {
if (word1->base >= minBase &&
- word1->base <= maxBase &&
- (delta = lastWord->primaryDelta(word1)) >=
- minCharSpacing * fontSize) {
- if (delta < maxWordSpacing * fontSize &&
- (!bestWord1 || word1->primaryCmp(bestWord1) < 0)) {
- bestWordBaseIdx = baseIdx;
- bestWord0 = word0;
- bestWord1 = word1;
+ word1->base <= maxBase) {
+ delta = lastWord->primaryDelta(word1);
+ if (delta < minCharSpacing * fontSize) {
+ overlap = gTrue;
+ break;
+ } else {
+ if (delta < wordSpacing &&
+ (!bestWord1 || word1->primaryCmp(bestWord1) < 0)) {
+ bestWordBaseIdx = baseIdx;
+ bestWord0 = word0;
+ bestWord1 = word1;
+ }
+ break;
}
- break;
}
}
}
- if (!bestWord1) {
+ if (overlap || !bestWord1) {
break;
}
@@ -1342,52 +1419,79 @@ void TextBlock::coalesce(UnicodeMap *uMap) {
// column assignment
nColumns = 0;
- for (i = 0; i < nLines; ++i) {
- line0 = lineArray[i];
- col1 = 0;
- for (j = 0; j < i; ++j) {
- line1 = lineArray[j];
- if (line1->primaryDelta(line0) >= 0) {
- col2 = line1->col[line1->len] + 1;
- } else {
- k = 0; // make gcc happy
- switch (rot) {
- case 0:
- for (k = 0;
- k < line1->len &&
- line0->xMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]);
- ++k) ;
- break;
- case 1:
- for (k = 0;
- k < line1->len &&
- line0->yMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]);
- ++k) ;
- break;
- case 2:
- for (k = 0;
- k < line1->len &&
- line0->xMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]);
- ++k) ;
- break;
- case 3:
- for (k = 0;
- k < line1->len &&
- line0->yMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]);
- ++k) ;
- break;
- }
- col2 = line1->col[k];
+ if (fixedPitch) {
+ for (i = 0; i < nLines; ++i) {
+ line0 = lineArray[i];
+ col1 = 0; // make gcc happy
+ switch (rot) {
+ case 0:
+ col1 = (int)((line0->xMin - xMin) / fixedPitch + 0.5);
+ break;
+ case 1:
+ col1 = (int)((line0->yMin - yMin) / fixedPitch + 0.5);
+ break;
+ case 2:
+ col1 = (int)((xMax - line0->xMax) / fixedPitch + 0.5);
+ break;
+ case 3:
+ col1 = (int)((yMax - line0->yMax) / fixedPitch + 0.5);
+ break;
}
- if (col2 > col1) {
- col1 = col2;
+ for (k = 0; k <= line0->len; ++k) {
+ line0->col[k] += col1;
+ }
+ if (line0->col[line0->len] > nColumns) {
+ nColumns = line0->col[line0->len];
}
}
- for (k = 0; k <= line0->len; ++k) {
- line0->col[k] += col1;
- }
- if (line0->col[line0->len] > nColumns) {
- nColumns = line0->col[line0->len];
+ } else {
+ for (i = 0; i < nLines; ++i) {
+ line0 = lineArray[i];
+ col1 = 0;
+ for (j = 0; j < i; ++j) {
+ line1 = lineArray[j];
+ if (line1->primaryDelta(line0) >= 0) {
+ col2 = line1->col[line1->len] + 1;
+ } else {
+ k = 0; // make gcc happy
+ switch (rot) {
+ case 0:
+ for (k = 0;
+ k < line1->len &&
+ line0->xMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]);
+ ++k) ;
+ break;
+ case 1:
+ for (k = 0;
+ k < line1->len &&
+ line0->yMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]);
+ ++k) ;
+ break;
+ case 2:
+ for (k = 0;
+ k < line1->len &&
+ line0->xMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]);
+ ++k) ;
+ break;
+ case 3:
+ for (k = 0;
+ k < line1->len &&
+ line0->yMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]);
+ ++k) ;
+ break;
+ }
+ col2 = line1->col[k];
+ }
+ if (col2 > col1) {
+ col1 = col2;
+ }
+ }
+ for (k = 0; k <= line0->len; ++k) {
+ line0->col[k] += col1;
+ }
+ if (line0->col[line0->len] > nColumns) {
+ nColumns = line0->col[line0->len];
+ }
}
}
gfree(lineArray);
@@ -1744,6 +1848,9 @@ TextPage::TextPage(GBool rawOrderA) {
nest = 0;
nTinyChars = 0;
lastCharOverlap = gFalse;
+ actualText = NULL;
+ actualTextLen = 0;
+ actualTextNBytes = 0;
if (!rawOrder) {
for (rot = 0; rot < 4; ++rot) {
pools[rot] = new TextPool();
@@ -1799,6 +1906,7 @@ void TextPage::clear() {
delete curWord;
curWord = NULL;
}
+ gfree(actualText);
if (rawOrder) {
while (rawWords) {
word = rawWords;
@@ -1817,6 +1925,8 @@ void TextPage::clear() {
gfree(blocks);
}
deleteGList(fonts, TextFontInfo);
+ deleteGList(underlines, TextUnderline);
+ deleteGList(links, TextLink);
curWord = NULL;
charPos = 0;
@@ -1824,6 +1934,9 @@ void TextPage::clear() {
curFontSize = 0;
nest = 0;
nTinyChars = 0;
+ actualText = NULL;
+ actualTextLen = 0;
+ actualTextNBytes = 0;
if (!rawOrder) {
for (rot = 0; rot < 4; ++rot) {
pools[rot] = new TextPool();
@@ -1834,6 +1947,8 @@ void TextPage::clear() {
rawWords = NULL;
rawLastWord = NULL;
fonts = new GList();
+ underlines = new GList();
+ links = new GList();
}
void TextPage::updateFont(GfxState *state) {
@@ -1931,12 +2046,18 @@ void TextPage::beginWord(GfxState *state, double x0, double y0) {
m[3] = m2[3];
}
if (fabs(m[0] * m[3]) > fabs(m[1] * m[2])) {
- rot = (m[3] < 0) ? 0 : 2;
+ rot = (m[0] > 0 || m[3] < 0) ? 0 : 2;
} else {
rot = (m[2] > 0) ? 1 : 3;
}
- curWord = new TextWord(state, rot, x0, y0, charPos, curFont, curFontSize);
+ // for vertical writing mode, the lines are effectively rotated 90
+ // degrees
+ if (state->getFont()->getWMode()) {
+ rot = (rot + 1) & 3;
+ }
+
+ curWord = new TextWord(state, rot, x0, y0, curFont, curFontSize);
}
void TextPage::addChar(GfxState *state, double x, double y,
@@ -1946,6 +2067,19 @@ void TextPage::addChar(GfxState *state, double x, double y,
GBool overlap;
int i;
+ // if we're in an ActualText span, save the position info (the
+ // ActualText chars will be added by TextPage::endActualText()).
+ if (actualText) {
+ if (!actualTextNBytes) {
+ actualTextX0 = x;
+ actualTextY0 = y;
+ }
+ actualTextX1 = x + dx;
+ actualTextY1 = y + dy;
+ actualTextNBytes += nBytes;
+ return;
+ }
+
// subtract char and word spacing from the dx,dy values
sp = state->getCharSpace();
if (c == (CharCode)0x20) {
@@ -1977,9 +2111,6 @@ void TextPage::addChar(GfxState *state, double x, double y,
// break words at space character
if (uLen == 1 && u[0] == (Unicode)0x20) {
- if (curWord) {
- ++curWord->charLen;
- }
charPos += nBytes;
endWord();
return;
@@ -1993,7 +2124,7 @@ void TextPage::addChar(GfxState *state, double x, double y,
// (2) this character overlaps the previous one (duplicated text), or
// (3) the previous character was an overlap (we want each duplicated
// character to be in a word by itself at this stage),
- // (4) the font size has changed
+ // (4) the font or font size has changed
if (curWord && curWord->len > 0) {
base = sp = delta = 0; // make gcc happy
switch (curWord->rot) {
@@ -2024,6 +2155,7 @@ void TextPage::addChar(GfxState *state, double x, double y,
sp < -minDupBreakOverlap * curWord->fontSize ||
sp > minWordBreakSpace * curWord->fontSize ||
fabs(base - curWord->base) > 0.5 ||
+ curFont != curWord->font ||
curFontSize != curWord->fontSize) {
endWord();
}
@@ -2057,15 +2189,46 @@ void TextPage::addChar(GfxState *state, double x, double y,
w1 /= uLen;
h1 /= uLen;
for (i = 0; i < uLen; ++i) {
- curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]);
+ curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1,
+ charPos, nBytes, u[i]);
}
}
- if (curWord) {
- curWord->charLen += nBytes;
- }
charPos += nBytes;
}
+void TextPage::incCharCount(int nChars) {
+ charPos += nChars;
+}
+
+void TextPage::beginActualText(GfxState *state, Unicode *u, int uLen) {
+ if (actualText) {
+ gfree(actualText);
+ }
+ actualText = (Unicode *)gmallocn(uLen, sizeof(Unicode));
+ memcpy(actualText, u, uLen * sizeof(Unicode));
+ actualTextLen = uLen;
+ actualTextNBytes = 0;
+}
+
+void TextPage::endActualText(GfxState *state) {
+ Unicode *u;
+
+ u = actualText;
+ actualText = NULL; // so we can call TextPage::addChar()
+ if (actualTextNBytes) {
+ // now that we have the position info for all of the text inside
+ // the marked content span, we feed the "ActualText" back through
+ // addChar()
+ addChar(state, actualTextX0, actualTextY0,
+ actualTextX1 - actualTextX0, actualTextY1 - actualTextY0,
+ 0, actualTextNBytes, u, actualTextLen);
+ }
+ gfree(u);
+ actualText = NULL;
+ actualTextLen = 0;
+ actualTextNBytes = gFalse;
+}
+
void TextPage::endWord() {
// This check is needed because Type 3 characters can contain
// text-drawing operations (when TextPage is being used via
@@ -2109,7 +2272,7 @@ void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, Link *link) {
links->append(new TextLink(xMin, yMin, xMax, yMax, link));
}
-void TextPage::coalesce(GBool physLayout, GBool doHTML) {
+void TextPage::coalesce(GBool physLayout, double fixedPitch, GBool doHTML) {
UnicodeMap *uMap;
TextPool *pool;
TextWord *word0, *word1, *word2;
@@ -2139,7 +2302,7 @@ void TextPage::coalesce(GBool physLayout, GBool doHTML) {
blkList = NULL;
lastBlk = NULL;
nBlocks = 0;
- primaryRot = -1;
+ primaryRot = 0;
#if 0 // for debugging
printf("*** initial words ***\n");
@@ -2603,7 +2766,7 @@ void TextPage::coalesce(GBool physLayout, GBool doHTML) {
//~ addition to primary rotation
// coalesce the block, and add it to the list
- blk->coalesce(uMap);
+ blk->coalesce(uMap, fixedPitch);
if (lastBlk) {
lastBlk->next = blk;
} else {
@@ -2611,11 +2774,12 @@ void TextPage::coalesce(GBool physLayout, GBool doHTML) {
}
lastBlk = blk;
count[rot] += blk->charCount;
- if (primaryRot < 0 || count[rot] > count[primaryRot]) {
- primaryRot = rot;
- }
++nBlocks;
}
+
+ if (count[rot] > count[primaryRot]) {
+ primaryRot = rot;
+ }
}
#if 0 // for debugging
@@ -2674,76 +2838,108 @@ void TextPage::coalesce(GBool physLayout, GBool doHTML) {
//----- column assignment
- // sort blocks into xy order for column assignment
- blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
- for (blk = blkList, i = 0; blk; blk = blk->next, ++i) {
- blocks[i] = blk;
- }
- qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpXYPrimaryRot);
+ if (physLayout && fixedPitch) {
- // column assignment
- for (i = 0; i < nBlocks; ++i) {
- blk0 = blocks[i];
- col1 = 0;
- for (j = 0; j < i; ++j) {
- blk1 = blocks[j];
- col2 = 0; // make gcc happy
+ blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
+ for (blk = blkList, i = 0; blk; blk = blk->next, ++i) {
+ blocks[i] = blk;
+ col1 = 0; // make gcc happy
switch (primaryRot) {
case 0:
- if (blk0->xMin > blk1->xMax) {
- col2 = blk1->col + blk1->nColumns + 3;
- } else if (blk1->xMax == blk1->xMin) {
- col2 = blk1->col;
- } else {
- col2 = blk1->col + (int)(((blk0->xMin - blk1->xMin) /
- (blk1->xMax - blk1->xMin)) *
- blk1->nColumns);
- }
+ col1 = (int)(blk->xMin / fixedPitch + 0.5);
break;
case 1:
- if (blk0->yMin > blk1->yMax) {
- col2 = blk1->col + blk1->nColumns + 3;
- } else if (blk1->yMax == blk1->yMin) {
- col2 = blk1->col;
- } else {
- col2 = blk1->col + (int)(((blk0->yMin - blk1->yMin) /
- (blk1->yMax - blk1->yMin)) *
- blk1->nColumns);
- }
+ col1 = (int)(blk->yMin / fixedPitch + 0.5);
break;
case 2:
- if (blk0->xMax < blk1->xMin) {
- col2 = blk1->col + blk1->nColumns + 3;
- } else if (blk1->xMin == blk1->xMax) {
- col2 = blk1->col;
- } else {
- col2 = blk1->col + (int)(((blk0->xMax - blk1->xMax) /
- (blk1->xMin - blk1->xMax)) *
- blk1->nColumns);
- }
+ col1 = (int)((pageWidth - blk->xMax) / fixedPitch + 0.5);
break;
case 3:
- if (blk0->yMax < blk1->yMin) {
- col2 = blk1->col + blk1->nColumns + 3;
- } else if (blk1->yMin == blk1->yMax) {
- col2 = blk1->col;
- } else {
- col2 = blk1->col + (int)(((blk0->yMax - blk1->yMax) /
- (blk1->yMin - blk1->yMax)) *
- blk1->nColumns);
- }
+ col1 = (int)((pageHeight - blk->yMax) / fixedPitch + 0.5);
break;
}
- if (col2 > col1) {
- col1 = col2;
+ blk->col = col1;
+ for (line = blk->lines; line; line = line->next) {
+ for (j = 0; j <= line->len; ++j) {
+ line->col[j] += col1;
+ }
}
}
- blk0->col = col1;
- for (line = blk0->lines; line; line = line->next) {
- for (j = 0; j <= line->len; ++j) {
- line->col[j] += col1;
+
+ } else {
+
+ // sort blocks into xy order for column assignment
+ blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
+ for (blk = blkList, i = 0; blk; blk = blk->next, ++i) {
+ blocks[i] = blk;
+ }
+ qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpXYPrimaryRot);
+
+ // column assignment
+ for (i = 0; i < nBlocks; ++i) {
+ blk0 = blocks[i];
+ col1 = 0;
+ for (j = 0; j < i; ++j) {
+ blk1 = blocks[j];
+ col2 = 0; // make gcc happy
+ switch (primaryRot) {
+ case 0:
+ if (blk0->xMin > blk1->xMax) {
+ col2 = blk1->col + blk1->nColumns + 3;
+ } else if (blk1->xMax == blk1->xMin) {
+ col2 = blk1->col;
+ } else {
+ col2 = blk1->col + (int)(((blk0->xMin - blk1->xMin) /
+ (blk1->xMax - blk1->xMin)) *
+ blk1->nColumns);
+ }
+ break;
+ case 1:
+ if (blk0->yMin > blk1->yMax) {
+ col2 = blk1->col + blk1->nColumns + 3;
+ } else if (blk1->yMax == blk1->yMin) {
+ col2 = blk1->col;
+ } else {
+ col2 = blk1->col + (int)(((blk0->yMin - blk1->yMin) /
+ (blk1->yMax - blk1->yMin)) *
+ blk1->nColumns);
+ }
+ break;
+ case 2:
+ if (blk0->xMax < blk1->xMin) {
+ col2 = blk1->col + blk1->nColumns + 3;
+ } else if (blk1->xMin == blk1->xMax) {
+ col2 = blk1->col;
+ } else {
+ col2 = blk1->col + (int)(((blk0->xMax - blk1->xMax) /
+ (blk1->xMin - blk1->xMax)) *
+ blk1->nColumns);
+ }
+ break;
+ case 3:
+ if (blk0->yMax < blk1->yMin) {
+ col2 = blk1->col + blk1->nColumns + 3;
+ } else if (blk1->yMin == blk1->yMax) {
+ col2 = blk1->col;
+ } else {
+ col2 = blk1->col + (int)(((blk0->yMax - blk1->yMax) /
+ (blk1->yMin - blk1->yMax)) *
+ blk1->nColumns);
+ }
+ break;
+ }
+ if (col2 > col1) {
+ col1 = col2;
+ }
+ }
+ blk0->col = col1;
+ for (line = blk0->lines; line; line = line->next) {
+ for (j = 0; j <= line->len; ++j) {
+ line->col[j] += col1;
+ }
}
}
+
}
#if 0 // for debugging
@@ -2753,7 +2949,7 @@ void TextPage::coalesce(GBool physLayout, GBool doHTML) {
blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->col,
blk->nColumns);
for (line = blk->lines; line; line = line->next) {
- printf(" line:\n");
+ printf(" line: col[0]=%d\n", line->col[0]);
for (word0 = line->words; word0; word0 = word0->next) {
printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '",
word0->xMin, word0->xMax, word0->yMin, word0->yMax,
@@ -2932,6 +3128,7 @@ GBool TextPage::findText(Unicode *s, int len,
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
GBool caseSensitive, GBool backward,
+ GBool wholeWord,
double *xMin, double *yMin,
double *xMax, double *yMax) {
TextBlock *blk;
@@ -2989,25 +3186,35 @@ GBool TextPage::findText(Unicode *s, int len,
blk = blocks[i];
// check: is the block above the top limit?
- if (!startAtTop && (backward ? blk->yMin > yStart : blk->yMax < yStart)) {
+ // (this only works if the page's primary rotation is zero --
+ // otherwise the blocks won't be sorted in the useful order)
+ if (!startAtTop && primaryRot == 0 &&
+ (backward ? blk->yMin > yStart : blk->yMax < yStart)) {
continue;
}
// check: is the block below the bottom limit?
- if (!stopAtBottom && (backward ? blk->yMax < yStop : blk->yMin > yStop)) {
+ // (this only works if the page's primary rotation is zero --
+ // otherwise the blocks won't be sorted in the useful order)
+ if (!stopAtBottom && primaryRot == 0 &&
+ (backward ? blk->yMax < yStop : blk->yMin > yStop)) {
break;
}
for (line = blk->lines; line; line = line->next) {
// check: is the line above the top limit?
- if (!startAtTop &&
+ // (this only works if the page's primary rotation is zero --
+ // otherwise the lines won't be sorted in the useful order)
+ if (!startAtTop && primaryRot == 0 &&
(backward ? line->yMin > yStart : line->yMin < yStart)) {
continue;
}
// check: is the line below the bottom limit?
- if (!stopAtBottom &&
+ // (this only works if the page's primary rotation is zero --
+ // otherwise the lines won't be sorted in the useful order)
+ if (!stopAtBottom && primaryRot == 0 &&
(backward ? line->yMin < yStop : line->yMin > yStop)) {
continue;
}
@@ -3030,68 +3237,72 @@ GBool TextPage::findText(Unicode *s, int len,
j = backward ? m - len : 0;
p = txt + j;
while (backward ? j >= 0 : j <= m - len) {
+ if (!wholeWord ||
+ ((j == 0 || !unicodeTypeAlphaNum(txt[j - 1])) &&
+ (j + len == m || !unicodeTypeAlphaNum(txt[j + len])))) {
- // compare the strings
- for (k = 0; k < len; ++k) {
- if (p[k] != s2[k]) {
- break;
+ // compare the strings
+ for (k = 0; k < len; ++k) {
+ if (p[k] != s2[k]) {
+ break;
+ }
}
- }
- // found it
- if (k == len) {
- switch (line->rot) {
- case 0:
- xMin1 = line->edge[j];
- xMax1 = line->edge[j + len];
- yMin1 = line->yMin;
- yMax1 = line->yMax;
- break;
- case 1:
- xMin1 = line->xMin;
- xMax1 = line->xMax;
- yMin1 = line->edge[j];
- yMax1 = line->edge[j + len];
- break;
- case 2:
- xMin1 = line->edge[j + len];
- xMax1 = line->edge[j];
- yMin1 = line->yMin;
- yMax1 = line->yMax;
- break;
- case 3:
- xMin1 = line->xMin;
- xMax1 = line->xMax;
- yMin1 = line->edge[j + len];
- yMax1 = line->edge[j];
- break;
- }
- if (backward) {
- if ((startAtTop ||
- yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) &&
- (stopAtBottom ||
- yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) {
- if (!found ||
- yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) {
- xMin0 = xMin1;
- xMax0 = xMax1;
- yMin0 = yMin1;
- yMax0 = yMax1;
- found = gTrue;
- }
+ // found it
+ if (k == len) {
+ switch (line->rot) {
+ case 0:
+ xMin1 = line->edge[j];
+ xMax1 = line->edge[j + len];
+ yMin1 = line->yMin;
+ yMax1 = line->yMax;
+ break;
+ case 1:
+ xMin1 = line->xMin;
+ xMax1 = line->xMax;
+ yMin1 = line->edge[j];
+ yMax1 = line->edge[j + len];
+ break;
+ case 2:
+ xMin1 = line->edge[j + len];
+ xMax1 = line->edge[j];
+ yMin1 = line->yMin;
+ yMax1 = line->yMax;
+ break;
+ case 3:
+ xMin1 = line->xMin;
+ xMax1 = line->xMax;
+ yMin1 = line->edge[j + len];
+ yMax1 = line->edge[j];
+ break;
}
- } else {
- if ((startAtTop ||
- yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
- (stopAtBottom ||
- yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) {
- if (!found ||
- yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) {
- xMin0 = xMin1;
- xMax0 = xMax1;
- yMin0 = yMin1;
- yMax0 = yMax1;
- found = gTrue;
+ if (backward) {
+ if ((startAtTop ||
+ yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) &&
+ (stopAtBottom ||
+ yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) {
+ if (!found ||
+ yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) {
+ xMin0 = xMin1;
+ xMax0 = xMax1;
+ yMin0 = yMin1;
+ yMax0 = yMax1;
+ found = gTrue;
+ }
+ }
+ } else {
+ if ((startAtTop ||
+ yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
+ (stopAtBottom ||
+ yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) {
+ if (!found ||
+ yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) {
+ xMin0 = xMin1;
+ xMax0 = xMax1;
+ yMin0 = yMin1;
+ yMax0 = yMax1;
+ found = gTrue;
+ }
}
}
}
@@ -3367,10 +3578,9 @@ GBool TextPage::findCharRange(int pos, int length,
return gFalse;
}
- //~ this doesn't correctly handle:
- //~ - ranges split across multiple lines (the highlighted region
- //~ is the bounding box of all the parts of the range)
- //~ - cases where characters don't convert one-to-one into Unicode
+ //~ this doesn't correctly handle ranges split across multiple lines
+ //~ (the highlighted region is the bounding box of all the parts of
+ //~ the range)
first = gTrue;
xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy
xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy
@@ -3378,16 +3588,14 @@ GBool TextPage::findCharRange(int pos, int length,
blk = blocks[i];
for (line = blk->lines; line; line = line->next) {
for (word = line->words; word; word = word->next) {
- if (pos < word->charPos + word->charLen &&
- word->charPos < pos + length) {
- j0 = pos - word->charPos;
- if (j0 < 0) {
- j0 = 0;
- }
- j1 = pos + length - 1 - word->charPos;
- if (j1 >= word->len) {
- j1 = word->len - 1;
- }
+ if (pos < word->charPos[word->len] &&
+ pos + length > word->charPos[0]) {
+ for (j0 = 0;
+ j0 < word->len && pos >= word->charPos[j0 + 1];
+ ++j0) ;
+ for (j1 = word->len - 1;
+ j1 > j0 && pos + length <= word->charPos[j1];
+ --j1) ;
switch (line->rot) {
case 0:
xMin1 = word->edge[j0];
@@ -3491,7 +3699,9 @@ void TextPage::dump(void *outputStream, TextOutputFunc outputFunc,
delete s;
if (word->next &&
fabs(word->next->base - word->base) <
- maxIntraLineDelta * word->fontSize) {
+ maxIntraLineDelta * word->fontSize &&
+ word->next->xMin >
+ word->xMax - minDupBreakOverlap * word->fontSize) {
if (word->next->xMin > word->xMax + minWordSpacing * word->fontSize) {
(*outputFunc)(outputStream, space, spaceLen);
}
@@ -3752,7 +3962,9 @@ int TextPage::dumpFragment(Unicode *text, int len, UnicodeMap *uMap,
}
i = j;
// output a right-to-left section
- for (j = i; j < len && !unicodeTypeL(text[j]); ++j) ;
+ for (j = i;
+ j < len && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j]));
+ ++j) ;
if (j > i) {
s->append(rle, rleLen);
for (k = j - 1; k >= i; --k) {
@@ -3767,11 +3979,17 @@ int TextPage::dumpFragment(Unicode *text, int len, UnicodeMap *uMap,
} else {
+ // Note: This code treats numeric characters (European and
+ // Arabic/Indic) as left-to-right, which isn't strictly correct
+ // (incurs extra LRE/POPDF pairs), but does produce correct
+ // visual formatting.
s->append(rle, rleLen);
i = len - 1;
while (i >= 0) {
// output a right-to-left section
- for (j = i; j >= 0 && !unicodeTypeL(text[j]); --j) ;
+ for (j = i;
+ j >= 0 && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j]));
+ --j) ;
for (k = i; k > j; --k) {
n = uMap->mapUnicode(text[k], buf, sizeof(buf));
s->append(buf, n);
@@ -3816,14 +4034,16 @@ TextWordList *TextPage::makeWordList(GBool physLayout) {
// TextOutputDev
//------------------------------------------------------------------------
-static void outputToFile(void *stream, char *text, int len) {
+static void outputToFile(void *stream, const char *text, int len) {
fwrite(text, 1, len, (FILE *)stream);
}
TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA,
- GBool rawOrderA, GBool append) {
+ double fixedPitchA, GBool rawOrderA,
+ GBool append) {
text = NULL;
physLayout = physLayoutA;
+ fixedPitch = physLayout ? fixedPitchA : 0;
rawOrder = rawOrderA;
doHTML = gFalse;
ok = gTrue;
@@ -3840,7 +4060,7 @@ TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA,
} else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) {
needClose = gTrue;
} else {
- error(-1, "Couldn't open text file '%s'", fileName);
+ error(errIO, -1, "Couldn't open text file '{0:s}'", fileName);
ok = gFalse;
return;
}
@@ -3854,11 +4074,13 @@ TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA,
}
TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream,
- GBool physLayoutA, GBool rawOrderA) {
+ GBool physLayoutA, double fixedPitchA,
+ GBool rawOrderA) {
outputFunc = func;
outputStream = stream;
needClose = gFalse;
physLayout = physLayoutA;
+ fixedPitch = physLayout ? fixedPitchA : 0;
rawOrder = rawOrderA;
doHTML = gFalse;
text = new TextPage(rawOrderA);
@@ -3883,12 +4105,16 @@ void TextOutputDev::startPage(int pageNum, GfxState *state) {
void TextOutputDev::endPage() {
text->endPage();
- text->coalesce(physLayout, doHTML);
+ text->coalesce(physLayout, fixedPitch, doHTML);
if (outputStream) {
text->dump(outputStream, outputFunc, physLayout);
}
}
+void TextOutputDev::restoreState(GfxState *state) {
+ text->updateFont(state);
+}
+
void TextOutputDev::updateFont(GfxState *state) {
text->updateFont(state);
}
@@ -3903,7 +4129,19 @@ void TextOutputDev::drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode c, int nBytes, Unicode *u, int uLen) {
- text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
+ text->addChar(state, x - originX, y - originY, dx, dy, c, nBytes, u, uLen);
+}
+
+void TextOutputDev::incCharCount(int nChars) {
+ text->incCharCount(nChars);
+}
+
+void TextOutputDev::beginActualText(GfxState *state, Unicode *u, int uLen) {
+ text->beginActualText(state, u, uLen);
+}
+
+void TextOutputDev::endActualText(GfxState *state) {
+ text->endActualText(state);
}
void TextOutputDev::stroke(GfxState *state) {
@@ -4006,7 +4244,7 @@ void TextOutputDev::eoFill(GfxState *state) {
fill(state);
}
-void TextOutputDev::processLink(Link *link, Catalog *catalog) {
+void TextOutputDev::processLink(Link *link) {
double x1, y1, x2, y2;
int xMin, yMin, xMax, yMax, x, y;
@@ -4057,10 +4295,12 @@ GBool TextOutputDev::findText(Unicode *s, int len,
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
GBool caseSensitive, GBool backward,
+ GBool wholeWord,
double *xMin, double *yMin,
double *xMax, double *yMax) {
return text->findText(s, len, startAtTop, stopAtBottom,
- startAtLast, stopAtLast, caseSensitive, backward,
+ startAtLast, stopAtLast,
+ caseSensitive, backward, wholeWord,
xMin, yMin, xMax, yMax);
}
diff --git a/xpdf/TextOutputDev.h b/xpdf/TextOutputDev.h
index 3a424bb..e3bb26c 100644
--- a/xpdf/TextOutputDev.h
+++ b/xpdf/TextOutputDev.h
@@ -38,7 +38,7 @@ class TextPage;
//------------------------------------------------------------------------
-typedef void (*TextOutputFunc)(void *stream, char *text, int len);
+typedef void (*TextOutputFunc)(void *stream, const char *text, int len);
//------------------------------------------------------------------------
// TextFontInfo
@@ -85,14 +85,15 @@ public:
// Constructor.
TextWord(GfxState *state, int rotA, double x0, double y0,
- int charPosA, TextFontInfo *fontA, double fontSize);
+ TextFontInfo *fontA, double fontSize);
// Destructor.
~TextWord();
// Add a character to the word.
void addChar(GfxState *state, double x, double y,
- double dx, double dy, Unicode u);
+ double dx, double dy, int charPosA, int charLen,
+ Unicode u);
// Merge <word> onto the end of <this>.
void merge(TextWord *word);
@@ -126,8 +127,8 @@ public:
double *xMaxA, double *yMaxA);
double getFontSize() { return fontSize; }
int getRotation() { return rot; }
- int getCharPos() { return charPos; }
- int getCharLen() { return charLen; }
+ int getCharPos() { return charPos[0]; }
+ int getCharLen() { return charPos[len] - charPos[0]; }
GBool getSpaceAfter() { return spaceAfter; }
#endif
@@ -144,11 +145,11 @@ private:
Unicode *text; // the text
double *edge; // "near" edge x or y coord of each char
// (plus one extra entry for the last char)
- int len; // length of text and edge arrays
- int size; // size of text and edge arrays
- int charPos; // character position (within content stream)
- int charLen; // number of content stream characters in
- // this word
+ int *charPos; // character position (within content stream)
+ // of each char (plus one extra entry for
+ // the last char)
+ int len; // length of text/edge/charPos arrays
+ int size; // size of text/edge/charPos arrays
TextFontInfo *font; // font information
double fontSize; // font size
GBool spaceAfter; // set if there is a space between this
@@ -280,7 +281,7 @@ public:
void addWord(TextWord *word);
- void coalesce(UnicodeMap *uMap);
+ void coalesce(UnicodeMap *uMap, double fixedPitch);
// Update this block's priMin and priMax values, looking at <blk>.
void updatePriMinMax(TextBlock *blk);
@@ -429,6 +430,15 @@ public:
double dx, double dy,
CharCode c, int nBytes, Unicode *u, int uLen);
+ // Add <nChars> invisible characters.
+ void incCharCount(int nChars);
+
+ // Begin/end an "ActualText" span, where the char indexes are
+ // supplied by a marked content operator rather than the text
+ // drawing operators.
+ void beginActualText(GfxState *state, Unicode *u, int uLen);
+ void endActualText(GfxState *state);
+
// End the current word, sorting it into the list of words.
void endWord();
@@ -442,7 +452,7 @@ public:
void addLink(int xMin, int yMin, int xMax, int yMax, Link *link);
// Coalesce strings that look like parts of the same line.
- void coalesce(GBool physLayout, GBool doHTML);
+ void coalesce(GBool physLayout, double fixedPitch, GBool doHTML);
// Find a string. If <startAtTop> is true, starts looking at the
// top of the page; else if <startAtLast> is true, starts looking
@@ -455,6 +465,7 @@ public:
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
GBool caseSensitive, GBool backward,
+ GBool wholeWord,
double *xMin, double *yMin,
double *xMax, double *yMax);
@@ -502,6 +513,13 @@ private:
int nTinyChars; // number of "tiny" chars seen so far
GBool lastCharOverlap; // set if the last added char overlapped the
// previous char
+ Unicode *actualText; // current "ActualText" span
+ int actualTextLen;
+ double actualTextX0,
+ actualTextY0,
+ actualTextX1,
+ actualTextY1;
+ int actualTextNBytes;
TextPool *pools[4]; // a "pool" of TextWords for each rotation
TextFlow *flows; // linked list of flows
@@ -544,14 +562,16 @@ public:
// is maintained. If <rawOrder> is true, the text is kept in
// content stream order.
TextOutputDev(char *fileName, GBool physLayoutA,
- GBool rawOrderA, GBool append);
+ double fixedPitchA, GBool rawOrderA,
+ GBool append);
// Create a TextOutputDev which will write to a generic stream. If
// <physLayoutA> is true, the original physical layout of the text
// is maintained. If <rawOrder> is true, the text is kept in
// content stream order.
TextOutputDev(TextOutputFunc func, void *stream,
- GBool physLayoutA, GBool rawOrderA);
+ GBool physLayoutA, double fixedPitchA,
+ GBool rawOrderA);
// Destructor.
virtual ~TextOutputDev();
@@ -575,6 +595,10 @@ public:
// Does this device need non-text content?
virtual GBool needNonText() { return gFalse; }
+ // Does this device require incCharCount to be called for text on
+ // non-shown layers?
+ virtual GBool needCharCount() { return gTrue; }
+
//----- initialization and control
// Start a page.
@@ -583,6 +607,9 @@ public:
// End a page.
virtual void endPage();
+ //----- save/restore graphics state
+ virtual void restoreState(GfxState *state);
+
//----- update text state
virtual void updateFont(GfxState *state);
@@ -593,6 +620,9 @@ public:
double dx, double dy,
double originX, double originY,
CharCode c, int nBytes, Unicode *u, int uLen);
+ virtual void incCharCount(int nChars);
+ virtual void beginActualText(GfxState *state, Unicode *u, int uLen);
+ virtual void endActualText(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
@@ -600,7 +630,7 @@ public:
virtual void eoFill(GfxState *state);
//----- link borders
- virtual void processLink(Link *link, Catalog *catalog);
+ virtual void processLink(Link *link);
//----- special access
@@ -615,6 +645,7 @@ public:
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
GBool caseSensitive, GBool backward,
+ GBool wholeWord,
double *xMin, double *yMin,
double *xMax, double *yMax);
@@ -653,6 +684,9 @@ private:
TextPage *text; // text for the current page
GBool physLayout; // maintain original physical layout when
// dumping text
+ double fixedPitch; // if physLayout is true and this is non-zero,
+ // assume fixed-pitch characters with this
+ // width
GBool rawOrder; // keep text in content stream order
GBool doHTML; // extra processing for HTML conversion
GBool ok; // set up ok?
diff --git a/xpdf/UnicodeMap.cc b/xpdf/UnicodeMap.cc
index 2b8cb1f..31f0c21 100644
--- a/xpdf/UnicodeMap.cc
+++ b/xpdf/UnicodeMap.cc
@@ -45,8 +45,9 @@ UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
char *tok1, *tok2, *tok3;
if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
- error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
- encodingNameA->getCString());
+ error(errSyntaxError, -1,
+ "Couldn't find unicodeMap file for the '{0:t}' encoding",
+ encodingNameA);
return NULL;
}
@@ -64,7 +65,7 @@ UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
tok3 = tok2;
tok2 = tok1;
}
- nBytes = strlen(tok3) / 2;
+ nBytes = (int)strlen(tok3) / 2;
if (nBytes <= 4) {
if (map->len == size) {
size *= 2;
@@ -92,12 +93,14 @@ UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
eMap->nBytes = nBytes;
++map->eMapsLen;
} else {
- error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
- line, encodingNameA->getCString());
+ error(errSyntaxError, -1,
+ "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
+ line, encodingNameA);
}
} else {
- error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
- line, encodingNameA->getCString());
+ error(errSyntaxError, -1,
+ "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
+ line, encodingNameA);
}
++line;
}
@@ -121,7 +124,7 @@ UnicodeMap::UnicodeMap(GString *encodingNameA) {
#endif
}
-UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
UnicodeMapRange *rangesA, int lenA) {
encodingName = new GString(encodingNameA);
unicodeOut = unicodeOutA;
@@ -136,7 +139,7 @@ UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
#endif
}
-UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
UnicodeMapFunc funcA) {
encodingName = new GString(encodingNameA);
unicodeOut = unicodeOutA;
diff --git a/xpdf/UnicodeMap.h b/xpdf/UnicodeMap.h
index 0f86101..66c482c 100644
--- a/xpdf/UnicodeMap.h
+++ b/xpdf/UnicodeMap.h
@@ -53,12 +53,12 @@ public:
static UnicodeMap *parse(GString *encodingNameA);
// Create a resident UnicodeMap.
- UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+ UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
UnicodeMapRange *rangesA, int lenA);
// Create a resident UnicodeMap that uses a function instead of a
// list of ranges.
- UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+ UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
UnicodeMapFunc funcA);
~UnicodeMap();
diff --git a/xpdf/UnicodeMapTables.h b/xpdf/UnicodeMapTables.h
index 9c51034..073e474 100644
--- a/xpdf/UnicodeMapTables.h
+++ b/xpdf/UnicodeMapTables.h
@@ -2,7 +2,7 @@
//
// UnicodeMapTables.h
//
-// Copyright 2001-2003 Glyph & Cog, LLC
+// Copyright 2001-2009 Glyph & Cog, LLC
//
//========================================================================
@@ -64,7 +64,9 @@ static UnicodeMapRange latin1UnicodeMapRanges[] = {
{ 0xfb01, 0xfb01, 0x6669, 2 },
{ 0xfb02, 0xfb02, 0x666c, 2 },
{ 0xfb03, 0xfb03, 0x666669, 3 },
- { 0xfb04, 0xfb04, 0x66666c, 3 }
+ { 0xfb04, 0xfb04, 0x66666c, 3 },
+ { 0xfb05, 0xfb05, 0x7374, 2 },
+ { 0xfb06, 0xfb06, 0x7374, 2 }
};
#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange))
@@ -197,7 +199,9 @@ static UnicodeMapRange ascii7UnicodeMapRanges[] = {
{ 0xfb01, 0xfb01, 0x6669, 2 },
{ 0xfb02, 0xfb02, 0x666c, 2 },
{ 0xfb03, 0xfb03, 0x666669, 3 },
- { 0xfb04, 0xfb04, 0x66666c, 3 }
+ { 0xfb04, 0xfb04, 0x66666c, 3 },
+ { 0xfb05, 0xfb05, 0x7374, 2 },
+ { 0xfb06, 0xfb06, 0x7374, 2 }
};
#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange))
diff --git a/xpdf/UnicodeTypeTable.cc b/xpdf/UnicodeTypeTable.cc
index b896040..edd2970 100644
--- a/xpdf/UnicodeTypeTable.cc
+++ b/xpdf/UnicodeTypeTable.cc
@@ -11,7 +11,7 @@
#include "UnicodeTypeTable.h"
struct UnicodeMapTableEntry {
- char *vector;
+ const char *vector;
char type;
};
@@ -20,21 +20,21 @@ struct UnicodeCaseTableVector {
};
static UnicodeMapTableEntry typeTable[256] = {
- { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNLNNNNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' },
+ { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN###NNNNN################NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#N####NNNNLNNNNN####NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' },
{ NULL, 'L' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' },
{ "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLNNNNNNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' },
- { "RRRRNNNNNNNNNRNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRRNNNNNNNNNNRRRRRR", 'X' },
+ { "RRRR#########RNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNN####################RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' },
{ "RRRRRRRRRRRRRRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
{ NULL, 'N' },
- { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLNNLLLLLLLNNNNN", 'X' },
- { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLNNNNNNNNNNNNNNNN", 'X' },
- { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLL", 'X' },
+ { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL##LLLLLLLNNNNN", 'X' },
+ { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLL##NNNNNNNNNNNNNN", 'X' },
+ { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN#NLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
- { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNNNNLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
+ { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN#####LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ NULL, 'L' },
@@ -43,7 +43,7 @@ static UnicodeMapTableEntry typeTable[256] = {
{ NULL, 'L' },
{ NULL, 'L' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
- { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLLNLNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' },
+ { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL#LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' },
{ "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
{ NULL, 'L' },
@@ -52,11 +52,11 @@ static UnicodeMapTableEntry typeTable[256] = {
{ NULL, 'L' },
{ NULL, 'L' },
{ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' },
- { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
- { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLLNLLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
- { NULL, 'N' },
+ { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRN#####NNNNNNNNNNNNNNN#NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#L##########NNNL############NNN###################################NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
+ { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL#LLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
+ { "NNNNNNNNNNNNNNNNNN##NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
{ "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
- { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' },
+ { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN####################LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' },
{ NULL, 'N' },
{ NULL, 'N' },
{ NULL, 'N' },
@@ -271,11 +271,11 @@ static UnicodeMapTableEntry typeTable[256] = {
{ NULL, 'L' },
{ NULL, 'L' },
{ NULL, 'L' },
- { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' },
+ { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR#RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' },
{ NULL, 'R' },
{ "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' },
- { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' },
- { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLL", 'X' }
+ { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#N#NN#NNNNNNNNN#NN##NNNNN##NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' },
+ { "NNN###NNNNN################NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL#####NNN##NNNNNNNNNNNNNNNNNNNNNNNLL", 'X' }
};
static UnicodeCaseTableVector caseTable00 = {{
@@ -934,6 +934,17 @@ GBool unicodeTypeR(Unicode c) {
return getType(c) == 'R';
}
+GBool unicodeTypeNum(Unicode c) {
+ return getType(c) == '#';
+}
+
+GBool unicodeTypeAlphaNum(Unicode c) {
+ char t;
+
+ t = getType(c);
+ return t == 'L' || t == 'R' || t == '#';
+}
+
Unicode unicodeToUpper(Unicode c) {
int i;
diff --git a/xpdf/UnicodeTypeTable.h b/xpdf/UnicodeTypeTable.h
index 7103dbd..879363d 100644
--- a/xpdf/UnicodeTypeTable.h
+++ b/xpdf/UnicodeTypeTable.h
@@ -15,6 +15,10 @@ extern GBool unicodeTypeL(Unicode c);
extern GBool unicodeTypeR(Unicode c);
+extern GBool unicodeTypeNum(Unicode c);
+
+extern GBool unicodeTypeAlphaNum(Unicode c);
+
extern Unicode unicodeToUpper(Unicode c);
#endif
diff --git a/xpdf/XPDFApp.cc b/xpdf/XPDFApp.cc
index f9d2cd4..4f5af03 100644
--- a/xpdf/XPDFApp.cc
+++ b/xpdf/XPDFApp.cc
@@ -156,7 +156,6 @@ XPDFApp::XPDFApp(int *argc, char *argv[]) {
getResources();
viewers = new GList();
-
}
void XPDFApp::getResources() {
@@ -188,7 +187,8 @@ void XPDFApp::getResources() {
paperRGB[2] = xcol.blue >> 8;
paperPixel = xcol.pixel;
} else {
- error(-1, "Couldn't allocate color '%s'", resources.paperColor);
+ error(errIO, -1, "Couldn't allocate color '{0:s}'",
+ resources.paperColor);
}
}
if (XAllocNamedColor(display, colormap, resources.matteColor,
diff --git a/xpdf/XPDFCore.cc b/xpdf/XPDFCore.cc
index 827a86d..b98bc37 100644
--- a/xpdf/XPDFCore.cc
+++ b/xpdf/XPDFCore.cc
@@ -276,13 +276,13 @@ void XPDFCore::resizeToPage(int pg) {
}
void XPDFCore::update(int topPageA, int scrollXA, int scrollYA,
- double zoomA, int rotateA,
- GBool force, GBool addToHist) {
+ double zoomA, int rotateA, GBool force,
+ GBool addToHist, GBool adjustScrollX) {
int oldPage;
oldPage = topPage;
PDFCore::update(topPageA, scrollXA, scrollYA, zoomA, rotateA,
- force, addToHist);
+ force, addToHist, adjustScrollX);
linkAction = NULL;
if (doc && topPage != oldPage) {
if (updateCbk) {
@@ -387,7 +387,8 @@ void XPDFCore::endSelection(int wx, int wy) {
if (doc->okToCopy()) {
copySelection();
} else {
- error(-1, "Copying of text from this document is not allowed.");
+ error(errNotAllowed, -1,
+ "Copying of text from this document is not allowed.");
}
}
#endif
@@ -554,20 +555,26 @@ void XPDFCore::doAction(LinkAction *action) {
#else
fileName->append(" &");
#endif
- msg = new GString("About to execute the command:\n");
- msg->append(fileName);
- if (doQuestionDialog("Launching external application", msg)) {
+ if (globalParams->getLaunchCommand()) {
+ fileName->insert(0, ' ');
+ fileName->insert(0, globalParams->getLaunchCommand());
system(fileName->getCString());
+ } else {
+ msg = new GString("About to execute the command:\n");
+ msg->append(fileName);
+ if (doQuestionDialog("Launching external application", msg)) {
+ system(fileName->getCString());
+ }
+ delete msg;
}
delete fileName;
- delete msg;
}
break;
// URI action
case actionURI:
if (!(cmd = globalParams->getURLCommand())) {
- error(-1, "No urlCommand defined in config file");
+ error(errConfig, -1, "No urlCommand defined in config file");
break;
}
runCommand(cmd, ((LinkURI *)action)->getURI());
@@ -597,14 +604,15 @@ void XPDFCore::doAction(LinkAction *action) {
(*actionCbk)(actionCbkData, actionName->getCString());
}
} else {
- error(-1, "Unknown named action: '%s'", actionName->getCString());
+ error(errSyntaxError, -1,
+ "Unknown named action: '{0:t}'", actionName);
}
break;
// Movie action
case actionMovie:
if (!(cmd = globalParams->getMovieCommand())) {
- error(-1, "No movieCommand defined in config file");
+ error(errConfig, -1, "No movieCommand defined in config file");
break;
}
if (((LinkMovie *)action)->hasAnnotRef()) {
@@ -652,8 +660,8 @@ void XPDFCore::doAction(LinkAction *action) {
// unknown action type
case actionUnknown:
- error(-1, "Unknown link action type: '%s'",
- ((LinkUnknown *)action)->getAction()->getCString());
+ error(errSyntaxError, -1, "Unknown link action type: '{0:t}'",
+ ((LinkUnknown *)action)->getAction());
break;
}
}
@@ -686,10 +694,10 @@ void XPDFCore::runCommand(GString *cmdFmt, GString *arg) {
// Escape any characters in a URL which might cause problems when
// calling system().
GString *XPDFCore::mungeURL(GString *url) {
- static char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-_.~/?:@&=+,#%";
+ static const char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-_.~/?:@&=+,#%";
GString *newURL;
char c;
char buf[4];
@@ -712,9 +720,10 @@ GString *XPDFCore::mungeURL(GString *url) {
// find
//------------------------------------------------------------------------
-GBool XPDFCore::find(char *s, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly) {
- if (!PDFCore::find(s, caseSensitive, next, backward, onePageOnly)) {
+GBool XPDFCore::find(char *s, GBool caseSensitive, GBool next,
+ GBool backward, GBool wholeWord, GBool onePageOnly) {
+ if (!PDFCore::find(s, caseSensitive, next,
+ backward, wholeWord, onePageOnly)) {
XBell(display, 0);
return gFalse;
}
@@ -725,8 +734,10 @@ GBool XPDFCore::find(char *s, GBool caseSensitive,
}
GBool XPDFCore::findU(Unicode *u, int len, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly) {
- if (!PDFCore::findU(u, len, caseSensitive, next, backward, onePageOnly)) {
+ GBool next, GBool backward,
+ GBool wholeWord, GBool onePageOnly) {
+ if (!PDFCore::findU(u, len, caseSensitive, next,
+ backward, wholeWord, onePageOnly)) {
XBell(display, 0);
return gFalse;
}
@@ -961,7 +972,7 @@ void XPDFCore::initWindow() {
}
void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr,
- XtPointer callData) {
+ XtPointer callData) {
XPDFCore *core = (XPDFCore *)ptr;
XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
@@ -1034,7 +1045,8 @@ void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) {
sx = core->scrollX;
sy = core->scrollY;
}
- core->update(core->topPage, sx, sy, core->zoom, core->rotate, gTrue, gFalse);
+ core->update(core->topPage, sx, sy, core->zoom, core->rotate, gTrue, gFalse,
+ gFalse);
}
void XPDFCore::redrawCbk(Widget widget, XtPointer ptr, XtPointer callData) {
@@ -1062,7 +1074,7 @@ void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) {
LinkAction *action;
int pg, x, y;
double xu, yu;
- char *s;
+ const char *s;
KeySym key;
GBool ok;
@@ -1170,7 +1182,7 @@ void XPDFCore::updateTileData(PDFCoreTile *tileA, int xSrc, int ySrc,
w = tile->xMax - tile->xMin;
h = tile->yMax - tile->yMin;
image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, w, h, 8, 0);
- image->data = (char *)gmalloc(h * image->bytes_per_line);
+ image->data = (char *)gmallocn(h, image->bytes_per_line);
tile->image = image;
} else {
image = (XImage *)tile->image;
@@ -1410,20 +1422,20 @@ void XPDFCore::setCursor(Cursor cursor) {
currentCursor = cursor;
}
-GBool XPDFCore::doQuestionDialog(char *title, GString *msg) {
+GBool XPDFCore::doQuestionDialog(const char *title, GString *msg) {
return doDialog(XmDIALOG_QUESTION, gTrue, title, msg);
}
-void XPDFCore::doInfoDialog(char *title, GString *msg) {
+void XPDFCore::doInfoDialog(const char *title, GString *msg) {
doDialog(XmDIALOG_INFORMATION, gFalse, title, msg);
}
-void XPDFCore::doErrorDialog(char *title, GString *msg) {
+void XPDFCore::doErrorDialog(const char *title, GString *msg) {
doDialog(XmDIALOG_ERROR, gFalse, title, msg);
}
GBool XPDFCore::doDialog(int type, GBool hasCancel,
- char *title, GString *msg) {
+ const char *title, GString *msg) {
Widget dialog, scroll, text;
XtAppContext appContext;
Arg args[20];
@@ -1434,7 +1446,7 @@ GBool XPDFCore::doDialog(int type, GBool hasCancel,
n = 0;
XtSetArg(args[n], XmNdialogType, type); ++n;
XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
- s1 = XmStringCreateLocalized(title);
+ s1 = XmStringCreateLocalized((char *)title);
XtSetArg(args[n], XmNdialogTitle, s1); ++n;
s2 = NULL; // make gcc happy
if (msg->getLength() <= 80) {
diff --git a/xpdf/XPDFCore.h b/xpdf/XPDFCore.h
index 903e22b..be1dcfa 100644
--- a/xpdf/XPDFCore.h
+++ b/xpdf/XPDFCore.h
@@ -37,7 +37,8 @@ class LinkAction;
//------------------------------------------------------------------------
typedef void (*XPDFUpdateCbk)(void *data, GString *fileName,
- int pageNum, int numPages, char *linkLabel);
+ int pageNum, int numPages,
+ const char *linkLabel);
typedef void (*XPDFActionCbk)(void *data, char *action);
@@ -80,8 +81,8 @@ public:
// Update the display, given the specified parameters.
virtual void update(int topPageA, int scrollXA, int scrollYA,
- double zoomA, int rotateA,
- GBool force, GBool addToHist);
+ double zoomA, int rotateA, GBool force,
+ GBool addToHist, GBool adjustScrollX);
//----- page/position changes
@@ -89,14 +90,14 @@ public:
virtual GBool gotoPrevPage(int dec, GBool top, GBool bottom);
virtual GBool goForward();
virtual GBool goBackward();
+ void startPan(int wx, int wy);
+ void endPan(int wx, int wy);
//----- selection
void startSelection(int wx, int wy);
void endSelection(int wx, int wy);
void copySelection();
- void startPan(int wx, int wy);
- void endPan(int wx, int wy);
//----- hyperlinks
@@ -106,20 +107,21 @@ public:
//----- find
- virtual GBool find(char *s, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly);
+ virtual GBool find(char *s, GBool caseSensitive, GBool next,
+ GBool backward, GBool wholeWord, GBool onePageOnly);
virtual GBool findU(Unicode *u, int len, GBool caseSensitive,
- GBool next, GBool backward, GBool onePageOnly);
+ GBool next, GBool backward,
+ GBool wholeWord, GBool onePageOnly);
//----- simple modal dialogs
- GBool doQuestionDialog(char *title, GString *msg);
- void doInfoDialog(char *title, GString *msg);
- void doErrorDialog(char *title, GString *msg);
+ GBool doQuestionDialog(const char *title, GString *msg);
+ void doInfoDialog(const char *title, GString *msg);
+ void doErrorDialog(const char *title, GString *msg);
//----- password dialog
- GString *getPassword();
+ virtual GString *getPassword();
//----- misc access
@@ -177,7 +179,7 @@ private:
virtual void updateScrollbars();
void setCursor(Cursor cursor);
GBool doDialog(int type, GBool hasCancel,
- char *title, GString *msg);
+ const char *title, GString *msg);
static void dialogOkCbk(Widget widget, XtPointer ptr,
XtPointer callData);
static void dialogCancelCbk(Widget widget, XtPointer ptr,
diff --git a/xpdf/XPDFTree.cc b/xpdf/XPDFTree.cc
index 720197f..bae9cb0 100644
--- a/xpdf/XPDFTree.cc
+++ b/xpdf/XPDFTree.cc
@@ -6,6 +6,7 @@
//
//========================================================================
+#include <aconf.h>
#include <stdlib.h>
#include "gmem.h"
#include "XPDFTreeP.h"
@@ -721,6 +722,7 @@ static int layoutSubtree(XPDFTreeWidget w, Widget instigator,
Widget ew;
XPDFTreeEntry *child;
XPDFTreeConstraint c;
+ int dy;
ew = e->widget;
if (!XtIsManaged(ew)) {
@@ -743,7 +745,14 @@ static int layoutSubtree(XPDFTreeWidget w, Widget instigator,
ew->core.border_width);
#endif
}
- y += ew->core.height + 2 * ew->core.border_width;
+ dy = ew->core.height + 2 * ew->core.border_width;
+ // this is a kludge to avoid crashes if the widget becomes too
+ // tall
+ if ((int)y + dy > 32767) {
+ y = 32767;
+ } else {
+ y += dy;
+ }
}
}
@@ -762,7 +771,8 @@ static void calcSize(Widget widget, Widget instigator,
Dimension *totalHeight) {
XPDFTreeWidget w = (XPDFTreeWidget)widget;
XPDFTreeEntry *e;
- Dimension w1, h1, w2, h2;
+ int h1;
+ Dimension w1, w2, h2;
w1 = h1 = 0;
for (e = w->tree.root; e; e = e->next) {
@@ -770,18 +780,22 @@ static void calcSize(Widget widget, Widget instigator,
if (w2 > w1) {
w1 = w2;
}
- h1 += h2;
+ h1 += (int)h2;
}
w1 += xpdfTreeIndent + 2 * w->tree.marginWidth;
- h1 += 2 * w->tree.marginHeight;
+ h1 += 2 * (int)w->tree.marginHeight;
if (h1 == 0) {
h1 = 1;
+ } else if (h1 > 32767) {
+ // this is a kludge to avoid crashes if the widget becomes too
+ // tall
+ h1 = 32767;
}
if (!*totalWidth) {
*totalWidth = w1;
}
if (!*totalHeight) {
- *totalHeight = h1;
+ *totalHeight = (Dimension)h1;
}
}
@@ -792,7 +806,8 @@ static void calcSubtreeSize(XPDFTreeWidget w, Widget instigator,
XPDFTreeEntry *child;
XPDFTreeConstraint c;
XtWidgetGeometry geom;
- Dimension w1, h1, w2, h2;
+ int h1;
+ Dimension w1, w2, h2;
ew = e->widget;
if (!XtIsManaged(ew)) {
@@ -809,13 +824,14 @@ static void calcSubtreeSize(XPDFTreeWidget w, Widget instigator,
}
if (ew == instigator) {
w1 = ew->core.width;
- h1 = ew->core.height;
+ h1 = (int)ew->core.height;
} else {
XtQueryGeometry(ew, NULL, &geom);
w1 = (geom.request_mode & CWWidth) ? geom.width : ew->core.width;
- h1 = (geom.request_mode & CWHeight) ? geom.height : ew->core.height;
+ h1 = (int)((geom.request_mode & CWHeight) ? geom.height
+ : ew->core.height);
}
- h1 += 2 * ew->core.border_width;
+ h1 += 2 * (int)ew->core.border_width;
} else {
// root of tree
w1 = 0;
@@ -830,10 +846,14 @@ static void calcSubtreeSize(XPDFTreeWidget w, Widget instigator,
if (w2 > w1) {
w1 = w2;
}
- h1 += h2;
+ h1 += (int)h2;
}
}
+ // this is a kludge to avoid crashes if the widget becomes too tall
+ if (h1 > 32767) {
+ h1 = 32767;
+ }
*width = w1;
*height = h1;
}
diff --git a/xpdf/XPDFTree.h b/xpdf/XPDFTree.h
index 432b4ff..be7293a 100644
--- a/xpdf/XPDFTree.h
+++ b/xpdf/XPDFTree.h
@@ -9,6 +9,7 @@
#ifndef XPDFTREE_H
#define XPDFTREE_H
+#include <aconf.h>
#include <Xm/Xm.h>
extern "C" {
diff --git a/xpdf/XPDFTreeP.h b/xpdf/XPDFTreeP.h
index 1d786f4..85cb12e 100644
--- a/xpdf/XPDFTreeP.h
+++ b/xpdf/XPDFTreeP.h
@@ -9,6 +9,7 @@
#ifndef XPDFTREEP_H
#define XPDFTREEP_H
+#include <aconf.h>
#include <Xm/ManagerP.h>
#include "XPDFTree.h"
diff --git a/xpdf/XPDFViewer.cc b/xpdf/XPDFViewer.cc
index c15d3e6..2de349d 100644
--- a/xpdf/XPDFViewer.cc
+++ b/xpdf/XPDFViewer.cc
@@ -134,7 +134,7 @@
//------------------------------------------------------------------------
struct ZoomMenuInfo {
- char *label;
+ const char *label;
double zoom;
};
@@ -159,7 +159,7 @@ static ZoomMenuInfo zoomMenuInfo[nZoomMenuItems] = {
//------------------------------------------------------------------------
-#define cmdMaxArgs 2
+#define cmdMaxArgs 8
XPDFViewerCmd XPDFViewer::cmdTab[] = {
{ "about", 0, gFalse, gFalse, &XPDFViewer::cmdAbout },
@@ -205,6 +205,8 @@ XPDFViewerCmd XPDFViewer::cmdTab[] = {
{ "raise", 0, gFalse, gFalse, &XPDFViewer::cmdRaise },
{ "redraw", 0, gTrue, gFalse, &XPDFViewer::cmdRedraw },
{ "reload", 0, gTrue, gFalse, &XPDFViewer::cmdReload },
+ { "rotateCCW", 0, gTrue, gFalse, &XPDFViewer::cmdRotateCCW },
+ { "rotateCW", 0, gTrue, gFalse, &XPDFViewer::cmdRotateCW },
{ "run", 1, gFalse, gFalse, &XPDFViewer::cmdRun },
{ "scrollDown", 1, gTrue, gFalse, &XPDFViewer::cmdScrollDown },
{ "scrollDownNextPage", 1, gTrue, gFalse, &XPDFViewer::cmdScrollDownNextPage },
@@ -220,6 +222,7 @@ XPDFViewerCmd XPDFViewer::cmdTab[] = {
{ "scrollToTopLeft", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToTopLeft },
{ "scrollUp", 1, gTrue, gFalse, &XPDFViewer::cmdScrollUp },
{ "scrollUpPrevPage", 1, gTrue, gFalse, &XPDFViewer::cmdScrollUpPrevPage },
+ { "setSelection", 5, gTrue, gFalse, &XPDFViewer::cmdSetSelection },
{ "singlePageMode", 0, gFalse, gFalse, &XPDFViewer::cmdSinglePageMode },
{ "startPan", 0, gTrue, gTrue, &XPDFViewer::cmdStartPan },
{ "startSelection", 0, gTrue, gTrue, &XPDFViewer::cmdStartSelection },
@@ -359,9 +362,15 @@ XPDFViewer::XPDFViewer(XPDFApp *appA, PDFDoc *doc, int pageA,
XPDFViewer::~XPDFViewer() {
delete core;
- XmFontListFree(aboutBigFont);
- XmFontListFree(aboutVersionFont);
- XmFontListFree(aboutFixedFont);
+ if (aboutBigFont) {
+ XmFontListFree(aboutBigFont);
+ }
+ if (aboutVersionFont) {
+ XmFontListFree(aboutVersionFont);
+ }
+ if (aboutFixedFont) {
+ XmFontListFree(aboutFixedFont);
+ }
closeWindow();
#ifndef DISABLE_OUTLINE
if (outlineLabels) {
@@ -396,22 +405,27 @@ void XPDFViewer::clear() {
core->clear();
- // set up title, number-of-pages display
+ // set up title
title = app->getTitle() ? app->getTitle()->getCString()
: (char *)xpdfAppName;
XtVaSetValues(win, XmNtitle, title, XmNiconName, title, NULL);
- s = XmStringCreateLocalized("");
- XtVaSetValues(pageNumText, XmNlabelString, s, NULL);
- XmStringFree(s);
- s = XmStringCreateLocalized(" of 0");
- XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
- XmStringFree(s);
- // disable buttons
- XtVaSetValues(prevTenPageBtn, XmNsensitive, False, NULL);
- XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL);
- XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL);
- XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL);
+ if (toolBar != None) {
+
+ // set up number-of-pages display
+ s = XmStringCreateLocalized("");
+ XtVaSetValues(pageNumText, XmNlabelString, s, NULL);
+ XmStringFree(s);
+ s = XmStringCreateLocalized(" of 0");
+ XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
+ XmStringFree(s);
+
+ // disable buttons
+ XtVaSetValues(prevTenPageBtn, XmNsensitive, False, NULL);
+ XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL);
+ XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL);
+ XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL);
+ }
// remove the old outline
#ifndef DISABLE_OUTLINE
@@ -590,13 +604,13 @@ void XPDFViewer::mouseCbk(void *data, XEvent *event) {
int i;
if (event->type == ButtonPress) {
- if (event->xbutton.button >= 1 && event->xbutton.button <= 7) {
+ if (event->xbutton.button >= 1 && event->xbutton.button <= 32) {
keyCode = xpdfKeyCodeMousePress1 + event->xbutton.button - 1;
} else {
return;
}
} else if (event->type == ButtonRelease) {
- if (event->xbutton.button >= 1 && event->xbutton.button <= 7) {
+ if (event->xbutton.button >= 1 && event->xbutton.button <= 32) {
keyCode = xpdfKeyCodeMouseRelease1 + event->xbutton.button - 1;
} else {
return;
@@ -725,7 +739,7 @@ void XPDFViewer::execCmd(GString *cmd, XEvent *event) {
return;
err1:
- error(-1, "Invalid command syntax: '%s'", cmd->getCString());
+ error(errConfig, -1, "Invalid command syntax: '{0:t}'", cmd);
err2:
if (name) {
delete name;
@@ -834,10 +848,12 @@ void XPDFViewer::cmdFocusToDocWin(GString *args[], int nArgs,
void XPDFViewer::cmdFocusToPageNum(GString *args[], int nArgs,
XEvent *event) {
- XmTextFieldSetSelection(pageNumText, 0,
- strlen(XmTextFieldGetString(pageNumText)),
- XtLastTimestampProcessed(display));
- XmProcessTraversal(pageNumText, XmTRAVERSE_CURRENT);
+ if (toolBar != None) {
+ XmTextFieldSetSelection(pageNumText, 0,
+ strlen(XmTextFieldGetString(pageNumText)),
+ XtLastTimestampProcessed(display));
+ XmProcessTraversal(pageNumText, XmTRAVERSE_CURRENT);
+ }
}
void XPDFViewer::cmdFollowLink(GString *args[], int nArgs,
@@ -1066,13 +1082,31 @@ void XPDFViewer::cmdReload(GString *args[], int nArgs,
reloadFile();
}
+void XPDFViewer::cmdRotateCCW(GString *args[], int nArgs,
+ XEvent *event) {
+ int r;
+
+ r = core->getRotate();
+ r = (r == 0) ? 270 : r - 90;
+ displayPage(core->getPageNum(), core->getZoom(), r, gTrue, gFalse);
+}
+
+void XPDFViewer::cmdRotateCW(GString *args[], int nArgs,
+ XEvent *event) {
+ int r;
+
+ r = core->getRotate();
+ r = (r == 270) ? 0 : r + 90;
+ displayPage(core->getPageNum(), core->getZoom(), r, gTrue, gFalse);
+}
+
void XPDFViewer::cmdRun(GString *args[], int nArgs,
XEvent *event) {
GString *fmt, *cmd, *s;
LinkAction *action;
- double selLRX, selLRY, selURX, selURY;
- int selPage;
- GBool gotSel;
+ double selLRX, selLRY, selURX, selURY, mouseX, mouseY;
+ int selPage, mousePage;
+ GBool gotSel, gotMouse;
char buf[64];
char *p;
char c0, c1;
@@ -1081,7 +1115,7 @@ void XPDFViewer::cmdRun(GString *args[], int nArgs,
cmd = new GString();
fmt = args[0];
i = 0;
- gotSel = gFalse;
+ gotSel = gotMouse = gFalse;
while (i < fmt->getLength()) {
c0 = fmt->getChar(i);
if (c0 == '%' && i+1 < fmt->getLength()) {
@@ -1109,6 +1143,12 @@ void XPDFViewer::cmdRun(GString *args[], int nArgs,
delete s;
}
break;
+ case 'p':
+ if (core->getDoc()) {
+ sprintf(buf, "%d", core->getPageNum());
+ cmd->append(buf);
+ }
+ break;
case 'x':
case 'y':
case 'X':
@@ -1127,6 +1167,29 @@ void XPDFViewer::cmdRun(GString *args[], int nArgs,
(c1 == 'X') ? selLRX : selLRY);
cmd->append(buf);
break;
+ case 'i':
+ case 'j':
+ case 'k':
+ if (!gotMouse) {
+ if (event->type == ButtonPress || event->type == ButtonRelease) {
+ core->cvtWindowToUser(event->xbutton.x, event->xbutton.y,
+ &mousePage, &mouseX, &mouseY);
+ } else if (event->type == KeyPress) {
+ core->cvtWindowToUser(event->xkey.x, event->xkey.y,
+ &mousePage, &mouseX, &mouseY);
+ } else {
+ mousePage = 0;
+ mouseX = mouseY = 0;
+ }
+ gotMouse = gTrue;
+ }
+ if (c1 == 'i') {
+ sprintf(buf, "%d", mousePage);
+ } else {
+ sprintf(buf, "%g", (c1 == 'j') ? mouseX : mouseY);
+ }
+ cmd->append(buf);
+ break;
default:
cmd->append(c1);
break;
@@ -1250,6 +1313,19 @@ void XPDFViewer::cmdScrollUpPrevPage(GString *args[], int nArgs,
core->scrollUpPrevPage(atoi(args[0]->getCString()));
}
+void XPDFViewer::cmdSetSelection(GString *args[], int nArgs, XEvent *event) {
+ int pg, ulx, uly, lrx, lry;
+
+ pg = atoi(args[0]->getCString());
+ core->cvtUserToDev(core->getPageNum(),
+ atof(args[1]->getCString()), atof(args[2]->getCString()),
+ &ulx, &uly);
+ core->cvtUserToDev(core->getPageNum(),
+ atof(args[3]->getCString()), atof(args[4]->getCString()),
+ &lrx, &lry);
+ core->setSelection(pg, ulx, uly, lrx, lry);
+}
+
void XPDFViewer::cmdSinglePageMode(GString *args[], int nArgs,
XEvent *event) {
Widget btn;
@@ -1707,7 +1783,7 @@ void XPDFViewer::initToolbar(Widget parent) {
XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n;
XtSetArg(args[n], XmNcolumns, 7); ++n;
for (i = 0; i < nZoomMenuItems; ++i) {
- st[i] = XmStringCreateLocalized(zoomMenuInfo[i].label);
+ st[i] = XmStringCreateLocalized((char *)zoomMenuInfo[i].label);
}
XtSetArg(args[n], XmNitems, st); ++n;
XtSetArg(args[n], XmNitemCount, nZoomMenuItems); ++n;
@@ -2492,23 +2568,15 @@ void XPDFViewer::fullScreenToggleCbk(Widget widget, XtPointer ptr,
void XPDFViewer::rotateCCWCbk(Widget widget, XtPointer ptr,
XtPointer callData) {
XPDFViewer *viewer = (XPDFViewer *)ptr;
- int r;
- r = viewer->core->getRotate();
- r = (r == 0) ? 270 : r - 90;
- viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(),
- r, gTrue, gFalse);
+ viewer->cmdRotateCCW(NULL, 0, NULL);
}
void XPDFViewer::rotateCWCbk(Widget widget, XtPointer ptr,
XtPointer callData) {
XPDFViewer *viewer = (XPDFViewer *)ptr;
- int r;
- r = viewer->core->getRotate();
- r = (r == 270) ? 0 : r + 90;
- viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(),
- r, gTrue, gFalse);
+ viewer->cmdRotateCW(NULL, 0, NULL);
}
void XPDFViewer::zoomToSelectionCbk(Widget widget, XtPointer ptr,
@@ -2568,7 +2636,7 @@ void XPDFViewer::pageNumCbk(Widget widget, XtPointer ptr,
}
void XPDFViewer::updateCbk(void *data, GString *fileName,
- int pageNum, int numPages, char *linkString) {
+ int pageNum, int numPages, const char *linkString) {
XPDFViewer *viewer = (XPDFViewer *)data;
GString *title;
char buf[20];
@@ -2618,14 +2686,13 @@ void XPDFViewer::updateCbk(void *data, GString *fileName,
}
if (linkString) {
- s = XmStringCreateLocalized(linkString);
+ s = XmStringCreateLocalized((char *)linkString);
XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL);
XmStringFree(s);
}
}
}
-
//------------------------------------------------------------------------
// GUI code: outline
//------------------------------------------------------------------------
@@ -2840,7 +2907,7 @@ void XPDFViewer::initAboutDialog() {
//----- text
for (i = 0; aboutWinText[i]; ++i) {
n = 0;
- s = XmStringCreateLocalized(aboutWinText[i]);
+ s = XmStringCreateLocalized((char *)aboutWinText[i]);
XtSetArg(args[n], XmNlabelString, s); ++n;
XtSetArg(args[n], XmNfontList, aboutFixedFont); ++n;
sprintf(buf, "t%d", i);
@@ -2990,8 +3057,6 @@ void XPDFViewer::initFindDialog() {
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
XtSetArg(args[n], XmNleftWidget, findBackwardToggle); ++n;
XtSetArg(args[n], XmNleftOffset, 16); ++n;
- XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
- XtSetArg(args[n], XmNrightOffset, 4); ++n;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
XtSetArg(args[n], XmNbottomWidget, okBtn); ++n;
XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
@@ -3007,6 +3072,26 @@ void XPDFViewer::initFindDialog() {
XmCreateToggleButton(findDialog, "matchCase", args, n);
XmStringFree(s);
XtManageChild(findCaseSensitiveToggle);
+ n = 0;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
+ XtSetArg(args[n], XmNleftWidget, findCaseSensitiveToggle); ++n;
+ XtSetArg(args[n], XmNleftOffset, 16); ++n;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
+ XtSetArg(args[n], XmNrightOffset, 4); ++n;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
+ XtSetArg(args[n], XmNbottomWidget, okBtn); ++n;
+ XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
+#if XmVERSION <= 1
+ XtSetArg(args[n], XmNindicatorOn, True); ++n;
+#else
+ XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n;
+#endif
+ XtSetArg(args[n], XmNset, XmUNSET); ++n;
+ s = XmStringCreateLocalized("Whole words only");
+ XtSetArg(args[n], XmNlabelString, s); ++n;
+ findWholeWordToggle = XmCreateToggleButton(findDialog, "wholeWord", args, n);
+ XmStringFree(s);
+ XtManageChild(findWholeWordToggle);
//----- search string entry
n = 0;
@@ -3074,6 +3159,7 @@ void XPDFViewer::doFind(GBool next) {
XmToggleButtonGetState(findCaseSensitiveToggle),
next,
XmToggleButtonGetState(findBackwardToggle),
+ XmToggleButtonGetState(findWholeWordToggle),
gFalse);
if (XtWindow(findDialog)) {
XUndefineCursor(display, XtWindow(findDialog));
@@ -3407,7 +3493,7 @@ void XPDFViewer::printPrintCbk(Widget widget, XtPointer ptr,
doc = viewer->core->getDoc();
if (!doc->okToPrint()) {
- error(-1, "Printing this document is not allowed.");
+ error(errNotAllowed, -1, "Printing this document is not allowed.");
return;
}
@@ -3434,9 +3520,8 @@ void XPDFViewer::printPrintCbk(Widget widget, XtPointer ptr,
lastPage = doc->getNumPages();
}
- psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
- doc->getCatalog(), firstPage, lastPage,
- psModePS);
+ psOut = new PSOutputDev(psFileName->getCString(), doc,
+ firstPage, lastPage, psModePS);
if (psOut->isOk()) {
doc->displayPages(psOut, firstPage, lastPage, 72, 72,
0, gTrue, globalParams->getPSCrop(), gTrue);
diff --git a/xpdf/XPDFViewer.h b/xpdf/XPDFViewer.h
index 2be27e1..8a345e8 100644
--- a/xpdf/XPDFViewer.h
+++ b/xpdf/XPDFViewer.h
@@ -46,7 +46,7 @@ class XPDFViewer;
//------------------------------------------------------------------------
struct XPDFViewerCmd {
- char *name;
+ const char *name;
int nArgs;
GBool requiresDoc;
GBool requiresEvent;
@@ -143,6 +143,8 @@ private:
void cmdRaise(GString *args[], int nArgs, XEvent *event);
void cmdRedraw(GString *args[], int nArgs, XEvent *event);
void cmdReload(GString *args[], int nArgs, XEvent *event);
+ void cmdRotateCCW(GString *args[], int nArgs, XEvent *event);
+ void cmdRotateCW(GString *args[], int nArgs, XEvent *event);
void cmdRun(GString *args[], int nArgs, XEvent *event);
void cmdScrollDown(GString *args[], int nArgs, XEvent *event);
void cmdScrollDownNextPage(GString *args[], int nArgs, XEvent *event);
@@ -158,6 +160,7 @@ private:
void cmdScrollToTopLeft(GString *args[], int nArgs, XEvent *event);
void cmdScrollUp(GString *args[], int nArgs, XEvent *event);
void cmdScrollUpPrevPage(GString *args[], int nArgs, XEvent *event);
+ void cmdSetSelection(GString *args[], int nArgs, XEvent *event);
void cmdSinglePageMode(GString *args[], int nArgs, XEvent *event);
void cmdStartPan(GString *args[], int nArgs, XEvent *event);
void cmdStartSelection(GString *args[], int nArgs, XEvent *event);
@@ -238,7 +241,7 @@ private:
static void pageNumCbk(Widget widget, XtPointer ptr,
XtPointer callData);
static void updateCbk(void *data, GString *fileName,
- int pageNum, int numPages, char *linkString);
+ int pageNum, int numPages, const char *linkString);
//----- GUI code: outline
#ifndef DISABLE_OUTLINE
@@ -337,6 +340,7 @@ private:
Widget findText;
Widget findBackwardToggle;
Widget findCaseSensitiveToggle;
+ Widget findWholeWordToggle;
Widget saveAsDialog;
diff --git a/xpdf/XRef.cc b/xpdf/XRef.cc
index 6a5b6c8..83322c3 100644
--- a/xpdf/XRef.cc
+++ b/xpdf/XRef.cc
@@ -16,6 +16,7 @@
#include <stddef.h>
#include <string.h>
#include <ctype.h>
+#include <limits.h>
#include "gmem.h"
#include "Object.h"
#include "Stream.h"
@@ -52,6 +53,8 @@ public:
// generation 0.
ObjectStream(XRef *xref, int objStrNumA);
+ GBool isOk() { return ok; }
+
~ObjectStream();
// Return the object number of this object stream.
@@ -67,6 +70,7 @@ private:
int nObjects; // number of objects in the stream
Object *objs; // the objects (length = nObjects)
int *objNums; // the object numbers (length = nObjects)
+ GBool ok;
};
ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
@@ -80,6 +84,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
nObjects = 0;
objs = NULL;
objNums = NULL;
+ ok = gFalse;
if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
goto err1;
@@ -105,6 +110,13 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
goto err1;
}
+ // this is an arbitrary limit to avoid integer overflow problems
+ // in the 'new Object[nObjects]' call (Acrobat apparently limits
+ // object streams to 100-200 objects)
+ if (nObjects > 1000000) {
+ error(errSyntaxError, -1, "Too many objects in an object stream");
+ goto err1;
+ }
objs = new Object[nObjects];
objNums = (int *)gmallocn(nObjects, sizeof(int));
offsets = (int *)gmallocn(nObjects, sizeof(int));
@@ -115,8 +127,8 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
parser = new Parser(xref, new Lexer(xref, str), gFalse);
for (i = 0; i < nObjects; ++i) {
- parser->getObj(&obj1);
- parser->getObj(&obj2);
+ parser->getObj(&obj1, gTrue);
+ parser->getObj(&obj2, gTrue);
if (!obj1.isInt() || !obj2.isInt()) {
obj1.free();
obj2.free();
@@ -161,10 +173,10 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
}
gfree(offsets);
+ ok = gTrue;
err1:
objStr.free();
- return;
}
ObjectStream::~ObjectStream() {
@@ -190,13 +202,14 @@ Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
// XRef
//------------------------------------------------------------------------
-XRef::XRef(BaseStream *strA) {
+XRef::XRef(BaseStream *strA, GBool repair) {
Guint pos;
Object obj;
ok = gTrue;
errCode = errNone;
size = 0;
+ last = -1;
entries = NULL;
streamEnds = NULL;
streamEndsLen = 0;
@@ -206,30 +219,32 @@ XRef::XRef(BaseStream *strA) {
permFlags = defPermFlags;
ownerPasswordOk = gFalse;
- // read the trailer
str = strA;
start = str->getStart();
- pos = getStartXref();
- // if there was a problem with the 'startxref' position, try to
- // reconstruct the xref table
- if (pos == 0) {
+ // if the 'repair' flag is set, try to reconstruct the xref table
+ if (repair) {
if (!(ok = constructXRef())) {
errCode = errDamaged;
return;
}
- // read the xref table
+ // if the 'repair' flag is not set, read the xref table
} else {
- while (readXRef(&pos)) ;
- // if there was a problem with the xref table,
- // try to reconstruct it
+ // read the trailer
+ pos = getStartXref();
+ if (pos == 0) {
+ errCode = errDamaged;
+ ok = gFalse;
+ return;
+ }
+
+ // read the xref table
+ while (readXRef(&pos)) ;
if (!ok) {
- if (!(ok = constructXRef())) {
- errCode = errDamaged;
- return;
- }
+ errCode = errDamaged;
+ return;
}
}
@@ -288,7 +303,7 @@ Guint XRef::getStartXref() {
if (i < 0) {
return 0;
}
- for (p = &buf[i+9]; isspace(*p); ++p) ;
+ for (p = &buf[i+9]; isspace(*p & 0xff); ++p) ;
lastXRefPos = strToUnsigned(p);
return lastXRefPos;
@@ -307,7 +322,7 @@ GBool XRef::readXRef(Guint *pos) {
new Lexer(NULL,
str->makeSubStream(start + *pos, gFalse, 0, &obj)),
gTrue);
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
// parse an old-style xref table
if (obj.isCmd("xref")) {
@@ -317,11 +332,11 @@ GBool XRef::readXRef(Guint *pos) {
// parse an xref stream
} else if (obj.isInt()) {
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
obj.free();
- if (!parser->getObj(&obj)->isCmd("obj")) {
+ if (!parser->getObj(&obj, gTrue)->isCmd("obj")) {
goto err1;
}
obj.free();
@@ -353,7 +368,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
int first, n, newSize, i;
while (1) {
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
if (obj.isCmd("trailer")) {
obj.free();
break;
@@ -363,7 +378,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
}
first = obj.getInt();
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
n = obj.getInt();
@@ -386,17 +401,17 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
size = newSize;
}
for (i = first; i < first + n; ++i) {
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
entry.offset = (Guint)obj.getInt();
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
entry.gen = obj.getInt();
obj.free();
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
if (obj.isCmd("n")) {
entry.type = xrefEntryUncompressed;
} else if (obj.isCmd("f")) {
@@ -417,6 +432,9 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
entries[0] = entries[1];
entries[1].offset = 0xffffffff;
}
+ if (i > last) {
+ last = i;
+ }
}
}
}
@@ -429,13 +447,25 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
// get the 'Prev' pointer
obj.getDict()->lookupNF("Prev", &obj2);
if (obj2.isInt()) {
- *pos = (Guint)obj2.getInt();
- more = gTrue;
+ pos2 = (Guint)obj2.getInt();
+ if (pos2 != *pos) {
+ *pos = pos2;
+ more = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Infinite loop in xref table");
+ more = gFalse;
+ }
} else if (obj2.isRef()) {
// certain buggy PDF generators generate "/Prev NNN 0 R" instead
// of "/Prev NNN"
- *pos = (Guint)obj2.getRefNum();
- more = gTrue;
+ pos2 = (Guint)obj2.getRefNum();
+ if (pos2 != *pos) {
+ *pos = pos2;
+ more = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Infinite loop in xref table");
+ more = gFalse;
+ }
} else {
more = gFalse;
}
@@ -624,6 +654,9 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
default:
return gFalse;
}
+ if (i > last) {
+ last = i;
+ }
}
}
@@ -647,7 +680,6 @@ GBool XRef::constructXRef() {
size = 0;
entries = NULL;
- error(-1, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
streamEndsLen = streamEndsSize = 0;
@@ -687,30 +719,30 @@ GBool XRef::constructXRef() {
delete parser;
// look for object
- } else if (isdigit(*p)) {
+ } else if (isdigit(*p & 0xff)) {
num = atoi(p);
if (num > 0) {
do {
++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
+ } while (*p && isdigit(*p & 0xff));
+ if (isspace(*p & 0xff)) {
do {
++p;
- } while (*p && isspace(*p));
- if (isdigit(*p)) {
+ } while (*p && isspace(*p & 0xff));
+ if (isdigit(*p & 0xff)) {
gen = atoi(p);
do {
++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
+ } while (*p && isdigit(*p & 0xff));
+ if (isspace(*p & 0xff)) {
do {
++p;
- } while (*p && isspace(*p));
+ } while (*p && isspace(*p & 0xff));
if (!strncmp(p, "obj", 3)) {
if (num >= size) {
newSize = (num + 1 + 255) & ~255;
if (newSize < 0) {
- error(-1, "Bad object number");
+ error(errSyntaxError, -1, "Bad object number");
return gFalse;
}
entries = (XRefEntry *)
@@ -726,6 +758,9 @@ GBool XRef::constructXRef() {
entries[num].offset = pos - start;
entries[num].gen = gen;
entries[num].type = xrefEntryUncompressed;
+ if (num > last) {
+ last = num;
+ }
}
}
}
@@ -737,7 +772,7 @@ GBool XRef::constructXRef() {
if (streamEndsLen == streamEndsSize) {
streamEndsSize += 64;
streamEnds = (Guint *)greallocn(streamEnds,
- streamEndsSize, sizeof(int));
+ streamEndsSize, sizeof(Guint));
}
streamEnds[streamEndsLen++] = pos;
}
@@ -746,7 +781,7 @@ GBool XRef::constructXRef() {
if (gotRoot)
return gTrue;
- error(-1, "Couldn't find trailer dictionary");
+ error(errSyntaxError, -1, "Couldn't find trailer dictionary");
return gFalse;
}
@@ -758,10 +793,10 @@ void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA,
encrypted = gTrue;
permFlags = permFlagsA;
ownerPasswordOk = ownerPasswordOkA;
- if (keyLengthA <= 16) {
+ if (keyLengthA <= 32) {
keyLength = keyLengthA;
} else {
- keyLength = 16;
+ keyLength = 32;
}
for (i = 0; i < keyLength; ++i) {
fileKey[i] = fileKeyA[i];
@@ -786,7 +821,7 @@ GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes);
}
-Object *XRef::fetch(int num, int gen, Object *obj) {
+Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
XRefEntry *e;
Parser *parser;
Object obj1, obj2, obj3;
@@ -808,9 +843,9 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
new Lexer(this,
str->makeSubStream(start + e->offset, gFalse, 0, &obj1)),
gTrue);
- parser->getObj(&obj1);
- parser->getObj(&obj2);
- parser->getObj(&obj3);
+ parser->getObj(&obj1, gTrue);
+ parser->getObj(&obj2, gTrue);
+ parser->getObj(&obj3, gTrue);
if (!obj1.isInt() || obj1.getInt() != num ||
!obj2.isInt() || obj2.getInt() != gen ||
!obj3.isCmd("obj")) {
@@ -820,8 +855,8 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
delete parser;
goto err;
}
- parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
- encAlgorithm, keyLength, num, gen);
+ parser->getObj(obj, gFalse, encrypted ? fileKey : (Guchar *)NULL,
+ encAlgorithm, keyLength, num, gen, recursion);
obj1.free();
obj2.free();
obj3.free();
@@ -829,14 +864,26 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
break;
case xrefEntryCompressed:
+#if 0 // Adobe apparently ignores the generation number on compressed objects
if (gen != 0) {
goto err;
}
+#endif
+ if (e->offset >= (Guint)size ||
+ entries[e->offset].type != xrefEntryUncompressed) {
+ error(errSyntaxError, -1, "Invalid object stream");
+ goto err;
+ }
if (!objStr || objStr->getObjStrNum() != (int)e->offset) {
if (objStr) {
delete objStr;
}
objStr = new ObjectStream(this, e->offset);
+ if (!objStr->isOk()) {
+ delete objStr;
+ objStr = NULL;
+ goto err;
+ }
}
objStr->getObject(e->gen, num, obj);
break;
@@ -884,13 +931,16 @@ GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
}
Guint XRef::strToUnsigned(char *s) {
- Guint x;
+ Guint x, d;
char *p;
- int i;
x = 0;
- for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) {
- x = 10 * x + (*p - '0');
+ for (p = s; *p && isdigit(*p & 0xff); ++p) {
+ d = *p - '0';
+ if (x > (UINT_MAX - d) / 10) {
+ break;
+ }
+ x = 10 * x + d;
}
return x;
}
diff --git a/xpdf/XRef.h b/xpdf/XRef.h
index 8a5e66c..f2c4ac3 100644
--- a/xpdf/XRef.h
+++ b/xpdf/XRef.h
@@ -43,7 +43,7 @@ class XRef {
public:
// Constructor. Read xref table from stream.
- XRef(BaseStream *strA);
+ XRef(BaseStream *strA, GBool repair);
// Destructor.
~XRef();
@@ -67,19 +67,20 @@ public:
GBool okToChange(GBool ignoreOwnerPW = gFalse);
GBool okToCopy(GBool ignoreOwnerPW = gFalse);
GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
+ int getPermFlags() { return permFlags; }
// Get catalog object.
Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
// Fetch an indirect reference.
- Object *fetch(int num, int gen, Object *obj);
+ Object *fetch(int num, int gen, Object *obj, int recursion = 0);
// Return the document's Info dictionary (if any).
Object *getDocInfo(Object *obj);
Object *getDocInfoNF(Object *obj);
// Return the number of objects in the xref table.
- int getNumObjects() { return size; }
+ int getNumObjects() { return last + 1; }
// Return the offset of the last xref table.
Guint getLastXRefPos() { return lastXRefPos; }
@@ -104,6 +105,7 @@ private:
// at beginning of file)
XRefEntry *entries; // xref entries
int size; // size of <entries> array
+ int last; // last used index in <entries>
int rootNum, rootGen; // catalog dict
GBool ok; // true if xref table is valid
int errCode; // error code (if <ok> is false)
@@ -116,7 +118,7 @@ private:
GBool encrypted; // true if file is encrypted
int permFlags; // permission bits
GBool ownerPasswordOk; // true if owner password is correct
- Guchar fileKey[16]; // file decryption key
+ Guchar fileKey[32]; // file decryption key
int keyLength; // length of key, in bytes
int encVersion; // encryption version
CryptAlgorithm encAlgorithm; // encryption algorithm
diff --git a/xpdf/XpdfPluginAPI.cc b/xpdf/XpdfPluginAPI.cc
index 789b45f..4c51537 100644
--- a/xpdf/XpdfPluginAPI.cc
+++ b/xpdf/XpdfPluginAPI.cc
@@ -51,7 +51,7 @@ XpdfObject _xpdfGetCatalog(XpdfDoc doc) {
HWND _xpdfWin32GetWindow(XpdfDoc doc) {
WinPDFCore *core;
- if (!(core = (WinPDFCore *)((PDFDoc *)doc)->getGUIData())) {
+ if (!(core = (WinPDFCore *)((PDFDoc *)doc)->getCore())) {
return NULL;
}
return core->getDrawFrame();
@@ -62,7 +62,7 @@ HWND _xpdfWin32GetWindow(XpdfDoc doc) {
Widget _xpdfXGetWindow(XpdfDoc doc) {
XPDFCore *core;
- if (!(core = (XPDFCore *)((PDFDoc *)doc)->getGUIData())) {
+ if (!(core = (XPDFCore *)((PDFDoc *)doc)->getCore())) {
return NULL;
}
return core->getWidget();
diff --git a/xpdf/about-text.h b/xpdf/about-text.h
index 50266bd..2ea7588 100644
--- a/xpdf/about-text.h
+++ b/xpdf/about-text.h
@@ -6,43 +6,19 @@
//
//========================================================================
-static char *aboutWinText[] = {
+static const char *aboutWinText[] = {
"http://www.foolabs.com/xpdf/",
"derekn@foolabs.com",
" ",
- "Licensed under the GNU General Public License (GPL).",
- "See the 'COPYING' file for details.",
+ "Licensed under the GNU General Public License (GPL) v2 or v3.",
+ "See the 'README' file for details.",
" ",
"Supports PDF version " supportedPDFVersionStr ".",
" ",
"The PDF data structures, operators, and specification",
"are copyright 1985-2006 Adobe Systems Inc.",
" ",
- "Mouse bindings:",
- " button 1: select text / follow link",
- " button 2: pan window",
- " button 3: menu",
- " ",
- "Key bindings:",
- " o = open file",
- " r = reload",
- " f / ctrl-F = find text",
- " ctrl-G = find next",
- " ctrl-P = print",
- " n = next page",
- " p = previous page",
- " <PgDn> = <space> = scroll down",
- " <PgUp> = <backspace> = <delete> = scroll up",
- " v = forward (history path)",
- " b = backward (history path)",
- " 0 / + / - = zoom zero / in / out",
- " z / w = zoom page / page width",
- " alt-F = toggle full-screen mode",
- " ctrl-L = redraw",
- " q = quit",
- " <home> / <end> = top / bottom of page",
- " <arrows> = scroll",
- " ",
- "For more information, please read the xpdf(1) man page.",
+ "For more information (including key and mouse bindings)",
+ "please read the xpdf(1) man page.",
NULL
};
diff --git a/xpdf/config.h b/xpdf/config.h
index 81d4dd0..998d345 100644
--- a/xpdf/config.h
+++ b/xpdf/config.h
@@ -2,7 +2,7 @@
//
// config.h
//
-// Copyright 1996-2007 Glyph & Cog, LLC
+// Copyright 1996-2011 Glyph & Cog, LLC
//
//========================================================================
@@ -14,13 +14,13 @@
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "3.02"
-#define xpdfVersionNum 3.02
+#define xpdfVersion "3.03"
+#define xpdfVersionNum 3.03
#define xpdfMajorVersion 3
-#define xpdfMinorVersion 2
+#define xpdfMinorVersion 3
#define xpdfUpdateVersion 0
#define xpdfMajorVersionStr "3"
-#define xpdfMinorVersionStr "2"
+#define xpdfMinorVersionStr "3"
#define xpdfUpdateVersionStr "0"
// supported PDF version
@@ -28,11 +28,11 @@
#define supportedPDFVersionNum 1.7
// copyright notice
-#define xpdfCopyright "Copyright 1996-2007 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2011 Glyph & Cog, LLC"
// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 3.02"
-#define xpdfCopyrightAmp "Copyright 1996-2007 Glyph && Cog, LLC"
+#define winxpdfVersion "WinXpdf 3.03"
+#define xpdfCopyrightAmp "Copyright 1996-2011 Glyph && Cog, LLC"
//------------------------------------------------------------------------
// paper size
@@ -52,7 +52,7 @@
//------------------------------------------------------------------------
// user config file name, relative to the user's home directory
-#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__))
+#if defined(VMS) || defined(WIN32)
#define xpdfUserConfigFile "xpdfrc"
#else
#define xpdfUserConfigFile ".xpdfrc"
@@ -74,12 +74,6 @@
// default maximum size of color cube to allocate
#define defaultRGBCube 5
-// number of fonts (combined t1lib, FreeType, X server) to cache
-#define xOutFontCacheSize 64
-
-// number of Type 3 fonts to cache
-#define xOutT3FontCacheSize 8
-
//------------------------------------------------------------------------
// popen
//------------------------------------------------------------------------
diff --git a/xpdf/pdfdetach.cc b/xpdf/pdfdetach.cc
new file mode 100644
index 0000000..4be3a48
--- /dev/null
+++ b/xpdf/pdfdetach.cc
@@ -0,0 +1,223 @@
+//========================================================================
+//
+// pdfdetach.cc
+//
+// Copyright 2010 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+#include <stdio.h>
+#include "gtypes.h"
+#include "gmem.h"
+#include "parseargs.h"
+#include "GlobalParams.h"
+#include "PDFDoc.h"
+#include "CharTypes.h"
+#include "UnicodeMap.h"
+#include "Error.h"
+#include "config.h"
+
+static GBool doList = gFalse;
+static int saveNum = 0;
+static GBool saveAll = gFalse;
+static char savePath[1024] = "";
+static char textEncName[128] = "";
+static char ownerPassword[33] = "\001";
+static char userPassword[33] = "\001";
+static char cfgFileName[256] = "";
+static GBool printVersion = gFalse;
+static GBool printHelp = gFalse;
+
+static ArgDesc argDesc[] = {
+ {"-list", argFlag, &doList, 0,
+ "list all embedded files"},
+ {"-save", argInt, &saveNum, 0,
+ "save the specified embedded file"},
+ {"-saveall", argFlag, &saveAll, 0,
+ "save all embedded files"},
+ {"-o", argString, savePath, sizeof(savePath),
+ "file name for the saved embedded file"},
+ {"-enc", argString, textEncName, sizeof(textEncName),
+ "output text encoding name"},
+ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
+ "owner password (for encrypted files)"},
+ {"-upw", argString, userPassword, sizeof(userPassword),
+ "user password (for encrypted files)"},
+ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
+ "configuration file to use in place of .xpdfrc"},
+ {"-v", argFlag, &printVersion, 0,
+ "print copyright and version info"},
+ {"-h", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"--help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-?", argFlag, &printHelp, 0,
+ "print usage information"},
+ {NULL}
+};
+
+int main(int argc, char *argv[]) {
+ GString *fileName;
+ UnicodeMap *uMap;
+ GString *ownerPW, *userPW;
+ PDFDoc *doc;
+ Unicode *name;
+ char uBuf[8];
+ char path[1024];
+ char *p;
+ GBool ok;
+ int exitCode;
+ int nFiles, nameLen, n, i, j;
+
+ exitCode = 99;
+
+ // parse args
+ ok = parseArgs(argDesc, &argc, argv);
+ if ((doList ? 1 : 0) +
+ ((saveNum != 0) ? 1 : 0) +
+ (saveAll ? 1 : 0) != 1) {
+ ok = gFalse;
+ }
+ if (!ok || argc != 2 || printVersion || printHelp) {
+ fprintf(stderr, "pdfdetach version %s\n", xpdfVersion);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersion) {
+ printUsage("pdfdetach", "<PDF-file>", argDesc);
+ }
+ goto err0;
+ }
+ fileName = new GString(argv[1]);
+
+ // read config file
+ globalParams = new GlobalParams(cfgFileName);
+ if (textEncName[0]) {
+ globalParams->setTextEncoding(textEncName);
+ }
+
+ // get mapping to output encoding
+ if (!(uMap = globalParams->getTextEncoding())) {
+ error(errConfig, -1, "Couldn't get text encoding");
+ delete fileName;
+ goto err1;
+ }
+
+ // open PDF file
+ if (ownerPassword[0] != '\001') {
+ ownerPW = new GString(ownerPassword);
+ } else {
+ ownerPW = NULL;
+ }
+ if (userPassword[0] != '\001') {
+ userPW = new GString(userPassword);
+ } else {
+ userPW = NULL;
+ }
+ doc = new PDFDoc(fileName, ownerPW, userPW);
+ if (userPW) {
+ delete userPW;
+ }
+ if (ownerPW) {
+ delete ownerPW;
+ }
+ if (!doc->isOk()) {
+ exitCode = 1;
+ goto err2;
+ }
+
+ nFiles = doc->getNumEmbeddedFiles();
+
+ // list embedded files
+ if (doList) {
+ printf("%d embedded files\n", nFiles);
+ for (i = 0; i < nFiles; ++i) {
+ printf("%d: ", i+1);
+ name = doc->getEmbeddedFileName(i);
+ nameLen = doc->getEmbeddedFileNameLength(i);
+ for (j = 0; j < nameLen; ++j) {
+ n = uMap->mapUnicode(name[j], uBuf, sizeof(uBuf));
+ fwrite(uBuf, 1, n, stdout);
+ }
+ fputc('\n', stdout);
+ }
+
+ // save all embedded files
+ } else if (saveAll) {
+ for (i = 0; i < nFiles; ++i) {
+ if (savePath[0]) {
+ n = strlen(savePath);
+ if (n > (int)sizeof(path) - 2) {
+ n = sizeof(path) - 2;
+ }
+ memcpy(path, savePath, n);
+ path[n] = '/';
+ p = path + n + 1;
+ } else {
+ p = path;
+ }
+ name = doc->getEmbeddedFileName(i);
+ nameLen = doc->getEmbeddedFileNameLength(i);
+ for (j = 0; j < nameLen; ++j) {
+ n = uMap->mapUnicode(name[j], uBuf, sizeof(uBuf));
+ if (p + n >= path + sizeof(path)) {
+ break;
+ }
+ memcpy(p, uBuf, n);
+ p += n;
+ }
+ *p = '\0';
+ if (!doc->saveEmbeddedFile(i, path)) {
+ error(errIO, -1, "Error saving embedded file as '{0:s}'", p);
+ exitCode = 2;
+ goto err2;
+ }
+ }
+
+ // save an embedded file
+ } else {
+ if (saveNum < 1 || saveNum > nFiles) {
+ error(errCommandLine, -1, "Invalid file number");
+ goto err2;
+ }
+ if (savePath[0]) {
+ p = savePath;
+ } else {
+ name = doc->getEmbeddedFileName(saveNum - 1);
+ nameLen = doc->getEmbeddedFileNameLength(saveNum - 1);
+ p = path;
+ for (j = 0; j < nameLen; ++j) {
+ n = uMap->mapUnicode(name[j], uBuf, sizeof(uBuf));
+ if (p + n >= path + sizeof(path)) {
+ break;
+ }
+ memcpy(p, uBuf, n);
+ p += n;
+ }
+ *p = '\0';
+ p = path;
+ }
+ if (!doc->saveEmbeddedFile(saveNum - 1, p)) {
+ error(errIO, -1, "Error saving embedded file as '{0:s}'", p);
+ exitCode = 2;
+ goto err2;
+ }
+ }
+
+ exitCode = 0;
+
+ // clean up
+ err2:
+ uMap->decRefCnt();
+ delete doc;
+ err1:
+ delete globalParams;
+ err0:
+
+ // check for memory leaks
+ Object::memCheck(stderr);
+ gMemReport(stderr);
+
+ return exitCode;
+}
diff --git a/xpdf/pdffonts.cc b/xpdf/pdffonts.cc
index d35825f..80403a1 100644
--- a/xpdf/pdffonts.cc
+++ b/xpdf/pdffonts.cc
@@ -12,6 +12,7 @@
#include <stddef.h>
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "parseargs.h"
#include "GString.h"
#include "gmem.h"
@@ -25,7 +26,7 @@
#include "config.h"
// NB: this must match the definition of GfxFontType in GfxFont.h.
-static char *fontTypeNames[] = {
+static const char *fontTypeNames[] = {
"unknown",
"Type 1",
"Type 1C",
@@ -149,8 +150,7 @@ int main(int argc, char *argv[]) {
if ((resDict = page->getResourceDict())) {
scanFonts(resDict, doc);
}
- annots = new Annots(doc->getXRef(), doc->getCatalog(),
- page->getAnnots(&obj1));
+ annots = new Annots(doc, page->getAnnots(&obj1));
obj1.free();
for (i = 0; i < annots->getNumAnnots(); ++i) {
if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
@@ -247,7 +247,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
}
// font name
- name = font->getOrigName();
+ name = font->getName();
// check for an embedded font
if (font->getType() == fontType3) {
@@ -291,7 +291,12 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
// add this font to the list
if (fontsLen == fontsSize) {
- fontsSize += 32;
+ if (fontsSize <= INT_MAX - 32) {
+ fontsSize += 32;
+ } else {
+ // let greallocn throw an exception
+ fontsSize = -1;
+ }
fonts = (Ref *)greallocn(fonts, fontsSize, sizeof(Ref));
}
fonts[fontsLen++] = *font->getID();
diff --git a/xpdf/pdfimages.cc b/xpdf/pdfimages.cc
index 549f090..dc79443 100644
--- a/xpdf/pdfimages.cc
+++ b/xpdf/pdfimages.cc
@@ -120,7 +120,8 @@ int main(int argc, char *argv[]) {
// check for copy permission
if (!doc->okToCopy()) {
- error(-1, "Copying of images from this document is not allowed.");
+ error(errNotAllowed, -1,
+ "Copying of images from this document is not allowed.");
exitCode = 3;
goto err1;
}
diff --git a/xpdf/pdfinfo.cc b/xpdf/pdfinfo.cc
index aa49273..ad482ac 100644
--- a/xpdf/pdfinfo.cc
+++ b/xpdf/pdfinfo.cc
@@ -31,15 +31,16 @@
#include "Error.h"
#include "config.h"
-static void printInfoString(Dict *infoDict, char *key, char *text,
+static void printInfoString(Dict *infoDict, const char *key, const char *text,
UnicodeMap *uMap);
-static void printInfoDate(Dict *infoDict, char *key, char *text);
-static void printBox(char *text, PDFRectangle *box);
+static void printInfoDate(Dict *infoDict, const char *key, const char *text);
+static void printBox(const char *text, PDFRectangle *box);
static int firstPage = 1;
static int lastPage = 0;
static GBool printBoxes = gFalse;
static GBool printMetadata = gFalse;
+static GBool rawDates = gFalse;
static char textEncName[128] = "";
static char ownerPassword[33] = "\001";
static char userPassword[33] = "\001";
@@ -56,6 +57,8 @@ static ArgDesc argDesc[] = {
"print the page bounding boxes"},
{"-meta", argFlag, &printMetadata, 0,
"print the document metadata (XML)"},
+ {"-rawdates", argFlag, &rawDates, 0,
+ "print the undecoded date strings directly from the PDF file"},
{"-enc", argString, textEncName, sizeof(textEncName),
"output text encoding name"},
{"-opw", argString, ownerPassword, sizeof(ownerPassword),
@@ -83,7 +86,8 @@ int main(int argc, char *argv[]) {
GString *ownerPW, *userPW;
UnicodeMap *uMap;
Page *page;
- Object info;
+ Object info, xfa;
+ Object *acroForm;
char buf[256];
double w, h, wISO, hISO;
FILE *f;
@@ -115,7 +119,7 @@ int main(int argc, char *argv[]) {
// get mapping to output encoding
if (!(uMap = globalParams->getTextEncoding())) {
- error(-1, "Couldn't get text encoding");
+ error(errConfig, -1, "Couldn't get text encoding");
delete fileName;
goto err1;
}
@@ -166,8 +170,15 @@ int main(int argc, char *argv[]) {
printInfoString(info.getDict(), "Author", "Author: ", uMap);
printInfoString(info.getDict(), "Creator", "Creator: ", uMap);
printInfoString(info.getDict(), "Producer", "Producer: ", uMap);
- printInfoDate(info.getDict(), "CreationDate", "CreationDate: ");
- printInfoDate(info.getDict(), "ModDate", "ModDate: ");
+ if (rawDates) {
+ printInfoString(info.getDict(), "CreationDate", "CreationDate: ",
+ uMap);
+ printInfoString(info.getDict(), "ModDate", "ModDate: ",
+ uMap);
+ } else {
+ printInfoDate(info.getDict(), "CreationDate", "CreationDate: ");
+ printInfoDate(info.getDict(), "ModDate", "ModDate: ");
+ }
}
info.free();
@@ -175,6 +186,19 @@ int main(int argc, char *argv[]) {
printf("Tagged: %s\n",
doc->getStructTreeRoot()->isDict() ? "yes" : "no");
+ // print form info
+ if ((acroForm = doc->getCatalog()->getAcroForm())->isDict()) {
+ acroForm->dictLookup("XFA", &xfa);
+ if (xfa.isStream() || xfa.isArray()) {
+ printf("Form: XFA\n");
+ } else {
+ printf("Form: AcroForm\n");
+ }
+ xfa.free();
+ } else {
+ printf("Form: none\n");
+ }
+
// print page count
printf("Pages: %d\n", doc->getNumPages());
@@ -295,7 +319,7 @@ int main(int argc, char *argv[]) {
return exitCode;
}
-static void printInfoString(Dict *infoDict, char *key, char *text,
+static void printInfoString(Dict *infoDict, const char *key, const char *text,
UnicodeMap *uMap) {
Object obj;
GString *s1;
@@ -332,7 +356,7 @@ static void printInfoString(Dict *infoDict, char *key, char *text,
obj.free();
}
-static void printInfoDate(Dict *infoDict, char *key, char *text) {
+static void printInfoDate(Dict *infoDict, const char *key, const char *text) {
Object obj;
char *s;
int year, mon, day, hour, min, sec, n;
@@ -373,15 +397,12 @@ static void printInfoDate(Dict *infoDict, char *key, char *text) {
} else {
fputs(s, stdout);
}
-
-
-
fputc('\n', stdout);
}
obj.free();
}
-static void printBox(char *text, PDFRectangle *box) {
+static void printBox(const char *text, PDFRectangle *box) {
printf("%s%8.2f %8.2f %8.2f %8.2f\n",
text, box->x1, box->y1, box->x2, box->y2);
}
diff --git a/xpdf/pdftoppm.cc b/xpdf/pdftoppm.cc
index acce660..cfc7236 100644
--- a/xpdf/pdftoppm.cc
+++ b/xpdf/pdftoppm.cc
@@ -83,7 +83,7 @@ int main(int argc, char *argv[]) {
PDFDoc *doc;
GString *fileName;
char *ppmRoot;
- char ppmFile[512];
+ GString *ppmFile;
GString *ownerPW, *userPW;
SplashColor paperColor;
SplashOutputDev *splashOut;
@@ -165,6 +165,7 @@ int main(int argc, char *argv[]) {
if (lastPage < 1 || lastPage > doc->getNumPages())
lastPage = doc->getNumPages();
+
// write PPM files
if (mono) {
paperColor[0] = 0xff;
@@ -180,10 +181,15 @@ int main(int argc, char *argv[]) {
for (pg = firstPage; pg <= lastPage; ++pg) {
doc->displayPage(splashOut, pg, resolution, resolution, 0,
gFalse, gTrue, gFalse);
- sprintf(ppmFile, "%.*s-%06d.%s",
- (int)sizeof(ppmFile) - 32, ppmRoot, pg,
- mono ? "pbm" : gray ? "pgm" : "ppm");
- splashOut->getBitmap()->writePNMFile(ppmFile);
+ if (!strcmp(ppmRoot, "-")) {
+ splashOut->getBitmap()->writePNMFile(stdout);
+ } else {
+ ppmFile = GString::format("{0:s}-{1:06d}.{2:s}",
+ ppmRoot, pg,
+ mono ? "pbm" : gray ? "pgm" : "ppm");
+ splashOut->getBitmap()->writePNMFile(ppmFile->getCString());
+ delete ppmFile;
+ }
}
delete splashOut;
diff --git a/xpdf/pdftops.cc b/xpdf/pdftops.cc
index 9ed024e..eae441f 100644
--- a/xpdf/pdftops.cc
+++ b/xpdf/pdftops.cc
@@ -280,7 +280,7 @@ int main(int argc, char *argv[]) {
// check for print permission
if (!doc->okToPrint()) {
- error(-1, "Printing this document is not allowed.");
+ error(errNotAllowed, -1, "Printing this document is not allowed.");
exitCode = 3;
goto err1;
}
@@ -309,13 +309,13 @@ int main(int argc, char *argv[]) {
// check for multi-page EPS or form
if ((doEPS || doForm) && firstPage != lastPage) {
- error(-1, "EPS and form files can only contain one page.");
+ error(errCommandLine, -1, "EPS and form files can only contain one page.");
goto err2;
}
// write PostScript file
- psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
- doc->getCatalog(), firstPage, lastPage, mode);
+ psOut = new PSOutputDev(psFileName->getCString(), doc,
+ firstPage, lastPage, mode);
if (psOut->isOk()) {
doc->displayPages(psOut, firstPage, lastPage, 72, 72,
0, !pageCrop, globalParams->getPSCrop(), gTrue);
diff --git a/xpdf/pdftotext.cc b/xpdf/pdftotext.cc
index f4373f6..5296ac4 100644
--- a/xpdf/pdftotext.cc
+++ b/xpdf/pdftotext.cc
@@ -29,13 +29,16 @@
#include "Error.h"
#include "config.h"
-static void printInfoString(FILE *f, Dict *infoDict, char *key,
- char *text1, char *text2, UnicodeMap *uMap);
-static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt);
+static void printInfoString(FILE *f, Dict *infoDict, const char *key,
+ const char *text1, const char *text2,
+ UnicodeMap *uMap);
+static void printInfoDate(FILE *f, Dict *infoDict, const char *key,
+ const char *fmt);
static int firstPage = 1;
static int lastPage = 0;
static GBool physLayout = gFalse;
+static double fixedPitch = 0;
static GBool rawOrder = gFalse;
static GBool htmlMeta = gFalse;
static char textEncName[128] = "";
@@ -55,6 +58,8 @@ static ArgDesc argDesc[] = {
"last page to convert"},
{"-layout", argFlag, &physLayout, 0,
"maintain original physical layout"},
+ {"-fixed", argFP, &fixedPitch, 0,
+ "assume fixed-pitch (or tabular) text"},
{"-raw", argFlag, &rawOrder, 0,
"keep strings in content stream order"},
{"-htmlmeta", argFlag, &htmlMeta, 0,
@@ -112,6 +117,9 @@ int main(int argc, char *argv[]) {
goto err0;
}
fileName = new GString(argv[1]);
+ if (fixedPitch) {
+ physLayout = gTrue;
+ }
// read config file
globalParams = new GlobalParams(cfgFileName);
@@ -132,7 +140,7 @@ int main(int argc, char *argv[]) {
// get mapping to output encoding
if (!(uMap = globalParams->getTextEncoding())) {
- error(-1, "Couldn't get text encoding");
+ error(errConfig, -1, "Couldn't get text encoding");
delete fileName;
goto err1;
}
@@ -162,7 +170,8 @@ int main(int argc, char *argv[]) {
// check for copy permission
if (!doc->okToCopy()) {
- error(-1, "Copying of text from this document is not allowed.");
+ error(errNotAllowed, -1,
+ "Copying of text from this document is not allowed.");
exitCode = 3;
goto err2;
}
@@ -195,7 +204,7 @@ int main(int argc, char *argv[]) {
f = stdout;
} else {
if (!(f = fopen(textFileName->getCString(), "wb"))) {
- error(-1, "Couldn't open text file '%s'", textFileName->getCString());
+ error(errIO, -1, "Couldn't open text file '{0:t}'", textFileName);
exitCode = 2;
goto err3;
}
@@ -232,7 +241,7 @@ int main(int argc, char *argv[]) {
// write text file
textOut = new TextOutputDev(textFileName->getCString(),
- physLayout, rawOrder, htmlMeta);
+ physLayout, fixedPitch, rawOrder, htmlMeta);
if (textOut->isOk()) {
doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0,
gFalse, gTrue, gFalse);
@@ -249,7 +258,7 @@ int main(int argc, char *argv[]) {
f = stdout;
} else {
if (!(f = fopen(textFileName->getCString(), "ab"))) {
- error(-1, "Couldn't open text file '%s'", textFileName->getCString());
+ error(errIO, -1, "Couldn't open text file '{0:t}'", textFileName);
exitCode = 2;
goto err3;
}
@@ -281,8 +290,9 @@ int main(int argc, char *argv[]) {
return exitCode;
}
-static void printInfoString(FILE *f, Dict *infoDict, char *key,
- char *text1, char *text2, UnicodeMap *uMap) {
+static void printInfoString(FILE *f, Dict *infoDict, const char *key,
+ const char *text1, const char *text2,
+ UnicodeMap *uMap) {
Object obj;
GString *s1;
GBool isUnicode;
@@ -318,7 +328,8 @@ static void printInfoString(FILE *f, Dict *infoDict, char *key,
obj.free();
}
-static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt) {
+static void printInfoDate(FILE *f, Dict *infoDict, const char *key,
+ const char *fmt) {
Object obj;
char *s;
diff --git a/xpdf/xpdf.cc b/xpdf/xpdf.cc
index 4305ee2..e5d91ca 100644
--- a/xpdf/xpdf.cc
+++ b/xpdf/xpdf.cc
@@ -103,7 +103,7 @@ static ArgDesc argDesc[] = {
{"-exec", argString, remoteCmd, sizeof(remoteCmd),
"execute command on xpdf remote server (with -remote only)"},
{"-reload", argFlag, &doRemoteReload, 0,
- "reload xpdf remove server window (with -remote only)"},
+ "reload xpdf remote server window (with -remote only)"},
{"-raise", argFlag, &doRemoteRaise, 0,
"raise xpdf remote server window (with -remote only)"},
{"-quit", argFlag, &doRemoteQuit, 0,